[vdr-plugin-satip] 01/03: Imported Upstream version 2.2.1

Frank Neumann fnu-guest at moszumanska.debian.org
Sat Apr 25 19:47:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

fnu-guest pushed a commit to branch master
in repository vdr-plugin-satip.

commit 866c02c43cf570199d71dae3d68b2c3c8d8d2367
Author: Frank Neumann <fnu at yavdr.org>
Date:   Sat Apr 25 21:23:50 2015 +0200

    Imported Upstream version 2.2.1
---
 HISTORY     |  10 ++++
 Makefile    |  17 +-----
 common.h    |  64 ++++++++++++++++++---
 config.h    |  36 ++++++------
 discover.c  |  76 +++++++++++++------------
 discover.h  |  14 +++--
 log.h       |   5 +-
 msearch.c   |   7 ++-
 param.c     |  18 +++---
 po/ca_ES.po |   6 +-
 po/de_DE.po |   6 +-
 po/es_ES.po |   6 +-
 po/fi_FI.po |   6 +-
 rtsp.c      | 185 ++++++++++++++++++++++++++++++++++++++++++++++++------------
 rtsp.h      |  12 +++-
 satip.c     |   2 +-
 16 files changed, 324 insertions(+), 146 deletions(-)

diff --git a/HISTORY b/HISTORY
index 6ea4717..9cee659 100644
--- a/HISTORY
+++ b/HISTORY
@@ -120,3 +120,13 @@ VDR Plugin 'satip' Revision History
 - Fixed memory deallocation errors.
 - Cleaned up all scan-build warnings.
 - Refactored the frontend handling.
+
+2015-04-04: Version 2.2.1
+
+- Improved RTSP error checking.
+- Got rid of SATIP_DEBUG.
+- Robustify the server discovery.
+- Fixed a memory leak in TinyXML implementation
+  (Thanks to Oliver Endriss).
+- Updated against SAT>IP protocol specification
+  version 1.2.2.
diff --git a/Makefile b/Makefile
index 2ff1695..b4c3bec 100644
--- a/Makefile
+++ b/Makefile
@@ -2,18 +2,10 @@
 # Makefile for SAT>IP plugin
 #
 
-# Debugging on/off
-
-#SATIP_DEBUG = 1
-
 # Use TinyXML instead of PugiXML
 
 #SATIP_USE_TINYXML = 1
 
-# Strip debug symbols?  Set eg. to /bin/true if not
-
-STRIP = strip
-
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
@@ -40,6 +32,7 @@ TMPDIR ?= /tmp
 
 export CFLAGS   = $(call PKGCFG,cflags)
 export CXXFLAGS = $(call PKGCFG,cxxflags)
+STRIP           ?= /bin/true
 
 ### The version number of VDR's plugin API:
 
@@ -75,12 +68,6 @@ else
 LIBS += -lpugixml
 endif
 
-ifdef SATIP_DEBUG
-ifeq ($(SATIP_DEBUG),1)
-DEFINES += -DDEBUG
-endif
-endif
-
 ifneq ($(strip $(GITTAG)),)
 DEFINES += -DGITVERSION='"-GIT-$(GITTAG)"'
 endif
@@ -142,9 +129,7 @@ install-i18n: $(I18Nmsgs)
 
 $(SOFILE): $(OBJS)
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
-ifndef SATIP_DEBUG
 	@$(STRIP) $@
-endif
 
 install-lib: $(SOFILE)
 	install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
diff --git a/common.h b/common.h
index 1cc713b..ac9ea20 100644
--- a/common.h
+++ b/common.h
@@ -35,7 +35,7 @@
 
 #define SATIP_CURL_EASY_GETINFO(X, Y, Z) \
   if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \
-     error("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y,  __FILE__, __LINE__, curl_easy_strerror(res), res); \
+     esyslog("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y,  __FILE__, __LINE__, curl_easy_strerror(res), res); \
      }
 
 #define SATIP_CURL_EASY_SETOPT(X, Y, Z) \
@@ -48,15 +48,15 @@
      esyslog("curl_easy_perform() [%s,%d] failed: %s (%d)",  __FILE__, __LINE__, curl_easy_strerror(res), res); \
      }
 
-#define ERROR_IF_FUNC(exp, errstr, func, ret)              \
-  do {                                                     \
-     if (exp) {                                            \
-        char tmp[64];                                      \
+#define ERROR_IF_FUNC(exp, errstr, func, ret)                \
+  do {                                                       \
+     if (exp) {                                              \
+        char tmp[64];                                        \
         esyslog("[%s,%d]: "errstr": %s", __FILE__, __LINE__, \
-              strerror_r(errno, tmp, sizeof(tmp)));        \
-        func;                                              \
-        ret;                                               \
-        }                                                  \
+                strerror_r(errno, tmp, sizeof(tmp)));        \
+        func;                                                \
+        ret;                                                 \
+        }                                                    \
   } while (0)
 
 
@@ -84,6 +84,52 @@
 
 #define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
 
+class cSatipMemoryBuffer {
+private:
+  enum {
+    eMaxDataSize = MEGABYTE(2)
+  };
+  char *dataM;
+  size_t sizeM;
+  void *AllocBuffer(void *ptrP, size_t sizeP)
+  {
+    // There might be a realloc() out there that doesn't like reallocing NULL pointers, so we take care of it here
+    if (ptrP)
+       return realloc(ptrP, sizeP);
+    else
+       return malloc(sizeP);
+  }
+  // to prevent copy constructor and assignment
+  cSatipMemoryBuffer(const cSatipMemoryBuffer&);
+  cSatipMemoryBuffer& operator=(const cSatipMemoryBuffer&);
+public:
+  cSatipMemoryBuffer() : dataM(NULL), sizeM(0) {}
+  ~cSatipMemoryBuffer() { Reset(); }
+  size_t Add(char *dataP, size_t sizeP)
+  {
+     if (sizeP > 0) {
+        size_t len = sizeM + sizeP + 1;
+        if (len < eMaxDataSize) {
+           dataM = (char *)AllocBuffer(dataM, len);
+           if (dataM) {
+              memcpy(&(dataM[sizeM]), dataP, sizeP);
+              sizeM += sizeP;
+              dataM[sizeM] = 0;
+              return sizeP;
+              }
+           else
+              esyslog("[%s,%d]: Failed to allocate memory", __FILE__, __LINE__);
+          }
+       else
+          esyslog("[%s,%d]: Buffer overflow", __FILE__, __LINE__);
+       }
+     return 0;
+  };
+  char *Data(void) { return dataM; }
+  size_t Size(void) { return sizeM; }
+  void Reset(void) { FREE_POINTER(dataM); sizeM = 0; };
+};
+
 uint16_t ts_pid(const uint8_t *bufP);
 uint8_t payload(const uint8_t *bufP);
 const char *id_pid(const u_short pidP);
diff --git a/config.h b/config.h
index 9dcd4fd..5b11614 100644
--- a/config.h
+++ b/config.h
@@ -34,24 +34,24 @@ public:
     eOperatingModeCount
   };
   enum eTraceMode {
-   eTraceModeNormal  = 0x0000,
-   eTraceModeDebug1  = 0x0001,
-   eTraceModeDebug2  = 0x0002,
-   eTraceModeDebug3  = 0x0004,
-   eTraceModeDebug4  = 0x0008,
-   eTraceModeDebug5  = 0x0010,
-   eTraceModeDebug6  = 0x0020,
-   eTraceModeDebug7  = 0x0040,
-   eTraceModeDebug8  = 0x0080,
-   eTraceModeDebug9  = 0x0100,
-   eTraceModeDebug10 = 0x0200,
-   eTraceModeDebug11 = 0x0400,
-   eTraceModeDebug12 = 0x0800,
-   eTraceModeDebug13 = 0x1000,
-   eTraceModeDebug14 = 0x2000,
-   eTraceModeDebug15 = 0x4000,
-   eTraceModeDebug16 = 0x8000,
-   eTraceModeMask    = 0xFFFF
+    eTraceModeNormal  = 0x0000,
+    eTraceModeDebug1  = 0x0001,
+    eTraceModeDebug2  = 0x0002,
+    eTraceModeDebug3  = 0x0004,
+    eTraceModeDebug4  = 0x0008,
+    eTraceModeDebug5  = 0x0010,
+    eTraceModeDebug6  = 0x0020,
+    eTraceModeDebug7  = 0x0040,
+    eTraceModeDebug8  = 0x0080,
+    eTraceModeDebug9  = 0x0100,
+    eTraceModeDebug10 = 0x0200,
+    eTraceModeDebug11 = 0x0400,
+    eTraceModeDebug12 = 0x0800,
+    eTraceModeDebug13 = 0x1000,
+    eTraceModeDebug14 = 0x2000,
+    eTraceModeDebug15 = 0x4000,
+    eTraceModeDebug16 = 0x8000,
+    eTraceModeMask    = 0xFFFF
   };
   cSatipConfig();
   unsigned int GetOperatingMode(void) const { return operatingModeM; }
diff --git a/discover.c b/discover.c
index 2a77325..990af68 100644
--- a/discover.c
+++ b/discover.c
@@ -47,43 +47,14 @@ void cSatipDiscover::Destroy(void)
      instanceS->Deactivate();
 }
 
-size_t cSatipDiscover::WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
+size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
 {
   cSatipDiscover *obj = reinterpret_cast<cSatipDiscover *>(dataP);
   size_t len = sizeP * nmembP;
   debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
 
-  if (obj) {
-     CURLcode res = CURLE_OK;
-     const char *desc = NULL, *model = NULL, *addr = NULL;
-#ifdef USE_TINYXML
-     TiXmlDocument doc;
-     char *xml = MALLOC(char, len + 1);
-     memcpy(xml, ptrP, len);
-     *(xml + len + 1) = 0;
-     doc.Parse((const char *)xml);
-     TiXmlHandle docHandle(&doc);
-     TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
-     if (descElement)
-        desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
-     TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
-     if (modelElement)
-        model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
-#else
-     pugi::xml_document doc;
-     pugi::xml_parse_result result = doc.load_buffer(ptrP, len);
-     if (result) {
-        pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
-        if (descNode)
-           desc = descNode.text().as_string("MyBrokenHardware");
-        pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
-        if (modelNode)
-           model = modelNode.text().as_string("DVBS2-1");
-        }
-#endif
-     SATIP_CURL_EASY_GETINFO(obj->handleM, CURLINFO_PRIMARY_IP, &addr);
-     obj->AddServer(addr, model, desc);
-     }
+  if (obj && (len > 0))
+     obj->dataBufferM.Add(ptrP, len);
 
   return len;
 }
@@ -120,6 +91,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data
 cSatipDiscover::cSatipDiscover()
 : cThread("SATIP discover"),
   mutexM(),
+  dataBufferM(),
   msearchM(*this),
   probeUrlListM(),
   handleM(curl_easy_init()),
@@ -170,7 +142,7 @@ void cSatipDiscover::Action(void)
            probeIntervalM.Set(eProbeIntervalMs);
            msearchM.Probe();
            mutexM.Lock();
-           serversM.Cleanup(eProbeIntervalMs * 2);
+           serversM.Cleanup(eCleanupTimeoutMs);
            mutexM.Unlock();
            }
         mutexM.Lock();
@@ -195,6 +167,7 @@ void cSatipDiscover::Fetch(const char *urlP)
 {
   debug1("%s (%s)", __PRETTY_FUNCTION__, urlP);
   if (handleM && !isempty(urlP)) {
+     const char *addr = NULL;
      long rc = 0;
      CURLcode res = CURLE_OK;
 
@@ -204,7 +177,7 @@ void cSatipDiscover::Fetch(const char *urlP)
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this);
 
      // Set callback
-     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::WriteCallback);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
 
      // No progress meter and no signaling
@@ -224,11 +197,44 @@ void cSatipDiscover::Fetch(const char *urlP)
      // Fetch the data
      SATIP_CURL_EASY_PERFORM(handleM);
      SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
-     if (rc != 200)
+     SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr);
+     if (rc == 200) {
+        ParseDeviceInfo(addr);
+        dataBufferM.Reset();
+        }
+     else
         error("Discovery detected invalid status code: %ld", rc);
      }
 }
 
+void cSatipDiscover::ParseDeviceInfo(const char *addrP)
+{
+  debug1("%s (%s)", __PRETTY_FUNCTION__, addrP);
+  const char *desc = NULL, *model = NULL;
+#ifdef USE_TINYXML
+  TiXmlDocument doc;
+  doc.Parse(dataBufferM.Data());
+  TiXmlHandle docHandle(&doc);
+  TiXmlElement *descElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("friendlyName").ToElement();
+  if (descElement)
+     desc = descElement->GetText() ? descElement->GetText() : "MyBrokenHardware";
+  TiXmlElement *modelElement = docHandle.FirstChild("root").FirstChild("device").FirstChild("satip:X_SATIPCAP").ToElement();
+  if (modelElement)
+     model = modelElement->GetText() ? modelElement->GetText() : "DVBS2-1";
+#else
+  pugi::xml_document doc;
+  if (doc.load_buffer(dataBufferM.Data(), dataBufferM.Size())) {
+     pugi::xml_node descNode = doc.first_element_by_path("root/device/friendlyName");
+     if (descNode)
+        desc = descNode.text().as_string("MyBrokenHardware");
+     pugi::xml_node modelNode = doc.first_element_by_path("root/device/satip:X_SATIPCAP");
+     if (modelNode)
+        model = modelNode.text().as_string("DVBS2-1");
+     }
+#endif
+  AddServer(addrP, model, desc);
+}
+
 void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP)
 {
   debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
diff --git a/discover.h b/discover.h
index 4984080..5942e42 100644
--- a/discover.h
+++ b/discover.h
@@ -13,6 +13,7 @@
 #include <vdr/thread.h>
 #include <vdr/tools.h>
 
+#include "common.h"
 #include "discoverif.h"
 #include "msearch.h"
 #include "server.h"
@@ -39,15 +40,17 @@ class cSatipDiscoverServers : public cList<cSatipDiscoverServer> {
 class cSatipDiscover : public cThread, public cSatipDiscoverIf {
 private:
   enum {
-    eSleepTimeoutMs   = 500,  // in milliseconds
-    eConnectTimeoutMs = 1500, // in milliseconds
-    eProbeTimeoutMs   = 2000, // in milliseconds
-    eProbeIntervalMs  = 60000 // in milliseconds
+    eSleepTimeoutMs   = 500,   // in milliseconds
+    eConnectTimeoutMs = 1500,  // in milliseconds
+    eProbeTimeoutMs   = 2000,  // in milliseconds
+    eProbeIntervalMs  = 60000, // in milliseconds
+    eCleanupTimeoutMs = 124000 // in milliseoonds
   };
   static cSatipDiscover *instanceS;
-  static size_t WriteCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
+  static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
   static int    DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
   cMutex mutexM;
+  cSatipMemoryBuffer dataBufferM;
   cSatipMsearch msearchM;
   cStringList probeUrlListM;
   CURL *handleM;
@@ -56,6 +59,7 @@ private:
   cSatipServers serversM;
   void Activate(void);
   void Deactivate(void);
+  void ParseDeviceInfo(const char *addrP);
   void AddServer(const char *addrP, const char *modelP, const char *descP);
   void Fetch(const char *urlP);
   // constructor
diff --git a/log.h b/log.h
index 4d5ee67..546d13e 100644
--- a/log.h
+++ b/log.h
@@ -34,9 +34,9 @@
 #define debug10(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug10) ? dsyslog("SATIP10: " x) : void() )
 // 0x0400: CI
 #define debug11(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug11) ? dsyslog("SATIP11: " x) : void() )
-// 0x0800: Discovery
+// 0x0800: Pids
 #define debug12(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug12) ? dsyslog("SATIP12: " x) : void() )
-// 0x1000: Pids
+// 0x1000: Discovery
 #define debug13(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug13) ? dsyslog("SATIP13: " x) : void() )
 // 0x2000: TBD
 #define debug14(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug14) ? dsyslog("SATIP14: " x) : void() )
@@ -46,4 +46,3 @@
 #define debug16(x...) void( SatipConfig.IsTraceMode(cSatipConfig::eTraceModeDebug16) ? dsyslog("SATIP16: " x) : void() )
 
 #endif // __SATIP_LOG_H
-
diff --git a/msearch.c b/msearch.c
index ab1fbad..f5edafc 100644
--- a/msearch.c
+++ b/msearch.c
@@ -45,6 +45,9 @@ void cSatipMsearch::Probe(void)
      cSatipPoller::GetInstance()->Register(*this);
      registeredM = true;
      }
+  // Send two queries with one second interval
+  Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
+  cCondWait::SleepMs(1000);
   Write(bcastAddressS, reinterpret_cast<const unsigned char *>(bcastMessageS), strlen(bcastMessageS));
 }
 
@@ -60,12 +63,12 @@ void cSatipMsearch::Process(void)
      int length;
      while ((length = Read(bufferM, bufferLenM)) > 0) {
            bufferM[min(length, int(bufferLenM - 1))] = 0;
-           debug12("%s len=%d buf=%s", __PRETTY_FUNCTION__, length, bufferM);
+           debug13("%s len=%d buf=%s", __PRETTY_FUNCTION__, length, bufferM);
            bool status = false, valid = false;
            char *s, *p = reinterpret_cast<char *>(bufferM), *location = NULL;
            char *r = strtok_r(p, "\r\n", &s);
            while (r) {
-                 debug12("%s r=%s", __PRETTY_FUNCTION__, r);
+                 debug13("%s r=%s", __PRETTY_FUNCTION__, r);
                  // Check the status code
                  // HTTP/1.1 200 OK
                  if (!status && startswith(r, "HTTP/1.1 200 OK"))
diff --git a/param.c b/param.c
index 03caa48..c71902d 100644
--- a/param.c
+++ b/param.c
@@ -147,9 +147,6 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
      cDvbTransponderParameters dtp(channelP->Parameters());
      int DataSlice = 0;
      int C2TuningFrequencyType = 0;
-     int Pilot = dtp.Pilot();
-     int T2SystemId = dtp.T2SystemId();
-     int SisoMiso = dtp.SisoMiso();
      float freq = channelP->Frequency();
      char type = cSource::ToChar(channelP->Source());
      cSource *source = Sources.Get(channelP->Source());
@@ -161,26 +158,31 @@ cString GetTransponderUrlParameters(const cChannel *channelP)
            freq /= 1000L;
 #define ST(s) if (strchr(s, type) && (strchr(s, '0' + dtp.System() + 1) || strchr(s, '*')))
 #define STBUFLEFT (sizeof(buffer) - (q - buffer))
+     ST(" S 1") { // to comply with SAT>IP protocol specification 1.2.2
+       dtp.SetPilot(PILOT_OFF);
+       dtp.SetModulation(QPSK);
+       dtp.SetRollOff(ROLLOFF_35);
+       }
                 q += snprintf(q,       STBUFLEFT, "freq=%s",          *dtoa(freq, "%lg"));
      ST(" S *") q += snprintf(q,       STBUFLEFT, "&src=%d",          ((src > 0) && (src <= 255)) ? src : 1);
      ST(" S *") q += snprintf(q,       STBUFLEFT, "&sr=%d",           channelP->Srate());
      ST("C  1") q += snprintf(q,       STBUFLEFT, "&sr=%d",           channelP->Srate());
      ST(" S *") q += snprintf(q,       STBUFLEFT, "&pol=%c",          tolower(dtp.Polarization()));
      ST("C T2") q += snprintf(q,       STBUFLEFT, "&plp=%d",          dtp.StreamId());
-     ST("  T2") q += snprintf(q,       STBUFLEFT, "&t2id=%d",         T2SystemId);
+     ST("  T2") q += snprintf(q,       STBUFLEFT, "&t2id=%d",         dtp.T2SystemId());
      ST("C  2") q += snprintf(q,       STBUFLEFT, "&c2tft=%d",        C2TuningFrequencyType);
      ST("C  2") q += snprintf(q,       STBUFLEFT, "&ds=%d",           DataSlice);
      ST("C  1") q += PrintUrlString(q, STBUFLEFT, dtp.Inversion(),    SatipInversionValues);
-     ST("  T2") q += PrintUrlString(q, STBUFLEFT, SisoMiso,           SatipSisoMisoValues);
+     ST("  T2") q += PrintUrlString(q, STBUFLEFT, dtp.SisoMiso(),     SatipSisoMisoValues);
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(),    SatipBandwidthValues);
      ST("C  2") q += PrintUrlString(q, STBUFLEFT, dtp.Bandwidth(),    SatipBandwidthValues);
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.Guard(),        SatipGuardValues);
      ST("CST*") q += PrintUrlString(q, STBUFLEFT, dtp.CoderateH(),    SatipCodeRateValues);
-     ST(" S 2") q += PrintUrlString(q, STBUFLEFT, Pilot,              SatipPilotValues);
-     ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(),   SatipModulationValues);
+     ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Pilot(),        SatipPilotValues);
+     ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(),   SatipModulationValues);
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(),   SatipModulationValues);
      ST("C  1") q += PrintUrlString(q, STBUFLEFT, dtp.Modulation(),   SatipModulationValues);
-     ST(" S 2") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(),      SatipRollOffValues);
+     ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.RollOff(),      SatipRollOffValues);
      ST(" S *") q += PrintUrlString(q, STBUFLEFT, dtp.System(),       SatipSystemValuesSat);
      ST("C  *") q += PrintUrlString(q, STBUFLEFT, dtp.System(),       SatipSystemValuesCable);
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(),       SatipSystemValuesTerrestrial);
diff --git a/po/ca_ES.po b/po/ca_ES.po
index e9ef289..a39cc70 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 2.2.0\n"
+"Project-Id-Version: vdr-satip 2.2.1\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-02-19 02:19+0200\n"
-"PO-Revision-Date: 2015-02-19 02:19+0200\n"
+"POT-Creation-Date: 2015-04-04 04:04+0300\n"
+"PO-Revision-Date: 2015-04-04 04:04+0300\n"
 "Last-Translator: Gabriel Bonich <gbonich at gmail.com>\n"
 "Language-Team: Catalan <vdr at linuxtv.org>\n"
 "Language: ca\n"
diff --git a/po/de_DE.po b/po/de_DE.po
index 9cd77ec..1f5be1e 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 2.2.0\n"
+"Project-Id-Version: vdr-satip 2.2.1\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-02-19 02:19+0200\n"
-"PO-Revision-Date: 2015-02-19 02:19+0200\n"
+"POT-Creation-Date: 2015-04-04 04:04+0300\n"
+"PO-Revision-Date: 2015-04-04 04:04+0300\n"
 "Last-Translator: Frank Neumann <fnu at yavdr.org>\n"
 "Language-Team: German <vdr at linuxtv.org>\n"
 "Language: de\n"
diff --git a/po/es_ES.po b/po/es_ES.po
index 724f5fb..4e0d772 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 2.2.0\n"
+"Project-Id-Version: vdr-satip 2.2.1\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-02-19 02:19+0200\n"
-"PO-Revision-Date: 2015-02-19 02:19+0200\n"
+"POT-Creation-Date: 2015-04-04 04:04+0300\n"
+"PO-Revision-Date: 2015-04-04 04:04+0300\n"
 "Last-Translator: Gabriel Bonich <gbonich at gmail.com>\n"
 "Language-Team: Spanish <vdr at linuxtv.org>\n"
 "Language: es\n"
diff --git a/po/fi_FI.po b/po/fi_FI.po
index 0b27822..94608f5 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 2.2.0\n"
+"Project-Id-Version: vdr-satip 2.2.1\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-02-19 02:19+0200\n"
-"PO-Revision-Date: 2015-02-19 02:19+0200\n"
+"POT-Creation-Date: 2015-04-04 04:04+0300\n"
+"PO-Revision-Date: 2015-04-04 04:04+0300\n"
 "Last-Translator: Rolf Ahrenberg\n"
 "Language-Team: Finnish <vdr at linuxtv.org>\n"
 "Language: fi\n"
diff --git a/rtsp.c b/rtsp.c
index e437d6b..562626e 100644
--- a/rtsp.c
+++ b/rtsp.c
@@ -15,9 +15,14 @@
 
 cSatipRtsp::cSatipRtsp(cSatipTunerIf &tunerP)
 : tunerM(tunerP),
+  headerBufferM(),
+  dataBufferM(),
   modeM(cmUnicast),
   handleM(NULL),
-  headerListM(NULL)
+  headerListM(NULL),
+  errorNoMoreM(""),
+  errorOutOfRangeM(""),
+  errorCheckSyntaxM("")
 {
   debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
   Create();
@@ -29,46 +34,26 @@ cSatipRtsp::~cSatipRtsp()
   Destroy();
 }
 
-size_t cSatipRtsp::HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
+size_t cSatipRtsp::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
 {
   cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
   size_t len = sizeP * nmembP;
   debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
 
-  char *s, *p = (char *)ptrP;
-  char *r = strtok_r(p, "\r\n", &s);
-
-  while (obj && r) {
-        debug16("%s (%zu): %s", __PRETTY_FUNCTION__, len, r);
-        r = skipspace(r);
-        if (strstr(r, "com.ses.streamID")) {
-           int streamid = -1;
-           if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
-              obj->tunerM.SetStreamId(streamid);
-           }
-        else if (strstr(r, "Session:")) {
-           int timeout = -1;
-           char *session = NULL;
-           if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
-              obj->tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
-           else if (sscanf(r, "Session:%m[^;]", &session) == 1)
-              obj->tunerM.SetSessionTimeout(skipspace(session), -1);
-           FREE_POINTER(session);
-           }
-        r = strtok_r(NULL, "\r\n", &s);
-        }
+  if (obj && (len > 0))
+     obj->headerBufferM.Add(ptrP, len);
 
   return len;
 }
 
-size_t cSatipRtsp::WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP)
+size_t cSatipRtsp::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP)
 {
   cSatipRtsp *obj = reinterpret_cast<cSatipRtsp *>(dataP);
   size_t len = sizeP * nmembP;
   debug16("%s len=%zu", __PRETTY_FUNCTION__, len);
 
-  if (obj && (len > 0))
-     obj->tunerM.ProcessApplicationData((u_char*)ptrP, len);
+  if (obj)
+     obj->dataBufferM.Add(ptrP, len);
 
   return len;
 }
@@ -216,10 +201,22 @@ bool cSatipRtsp::Setup(const char *uriP, int rtpPortP, int rtcpPortP)
      // Set header callback for catching the session and timeout
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipRtsp::HeaderCallback);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
      SATIP_CURL_EASY_PERFORM(handleM);
      // Session id is now known - disable header parsing
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, NULL);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, NULL);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
+     if (headerBufferM.Size() > 0) {
+        ParseHeader();
+        headerBufferM.Reset();
+        }
+     if (dataBufferM.Size() > 0) {
+        ParseData();
+        dataBufferM.Reset();
+        }
 
      result = ValidateLatestResponse(&rc);
      debug5("%s (%s, %d, %d) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rtpPortP, rtcpPortP, rc, processing.Elapsed(), tunerM.GetId());
@@ -253,11 +250,15 @@ bool cSatipRtsp::Describe(const char *uriP)
 
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
-     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::WriteCallback);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
      SATIP_CURL_EASY_PERFORM(handleM);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
+     if (dataBufferM.Size() > 0) {
+        tunerM.ProcessApplicationData((u_char *)dataBufferM.Data(), dataBufferM.Size());
+        dataBufferM.Reset();
+        }
 
      result = ValidateLatestResponse(&rc);
      debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
@@ -278,7 +279,15 @@ bool cSatipRtsp::Play(const char *uriP)
 
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
      SATIP_CURL_EASY_PERFORM(handleM);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
+     if (dataBufferM.Size() > 0) {
+        ParseData();
+        dataBufferM.Reset();
+        }
 
      result = ValidateLatestResponse(&rc);
      debug5("%s (%s) Response %ld in %" PRIu64 " ms [device %d]", __PRETTY_FUNCTION__, uriP, rc, processing.Elapsed(), tunerM.GetId());
@@ -299,7 +308,15 @@ bool cSatipRtsp::Teardown(const char *uriP)
 
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_STREAM_URI, uriP);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipRtsp::DataCallback);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this);
      SATIP_CURL_EASY_PERFORM(handleM);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, NULL);
+     SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, NULL);
+     if (dataBufferM.Size() > 0) {
+        ParseData();
+        dataBufferM.Reset();
+        }
 
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_CLIENT_CSEQ, 1L);
      SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_RTSP_SESSION_ID, NULL);
@@ -311,24 +328,122 @@ bool cSatipRtsp::Teardown(const char *uriP)
   return result;
 }
 
+void cSatipRtsp::ParseHeader(void)
+{
+  debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
+  char *s, *p = headerBufferM.Data();
+  char *r = strtok_r(p, "\r\n", &s);
+
+  while (r) {
+        debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r);
+        r = skipspace(r);
+        if (strstr(r, "com.ses.streamID")) {
+           int streamid = -1;
+           if (sscanf(r, "com.ses.streamID:%11d", &streamid) == 1)
+              tunerM.SetStreamId(streamid);
+           }
+        else if (strstr(r, "Session:")) {
+           int timeout = -1;
+           char *session = NULL;
+           if (sscanf(r, "Session:%m[^;];timeout=%11d", &session, &timeout) == 2)
+              tunerM.SetSessionTimeout(skipspace(session), timeout * 1000);
+           else if (sscanf(r, "Session:%m[^;]", &session) == 1)
+              tunerM.SetSessionTimeout(skipspace(session), -1);
+           FREE_POINTER(session);
+           }
+        r = strtok_r(NULL, "\r\n", &s);
+        }
+}
+
+void cSatipRtsp::ParseData(void)
+{
+  debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
+  char *s, *p = dataBufferM.Data();
+  char *r = strtok_r(p, "\r\n", &s);
+
+  while (r) {
+        debug16("%s (%zu): %s", __PRETTY_FUNCTION__, dataBufferM.Size(), r);
+        r = skipspace(r);
+        if (strstr(r, "No-More:")) {
+           char *tmp = NULL;
+           if (sscanf(r, "No-More:%m[^;]", &tmp) == 1) {
+              errorNoMoreM = skipspace(tmp);
+              debug3("%s No-More: %s [device %d]", __PRETTY_FUNCTION__, *errorNoMoreM, tunerM.GetId());
+              }
+           FREE_POINTER(tmp);
+           }
+        else if (strstr(r, "Out-of-Range:")) {
+           char *tmp = NULL;
+           if (sscanf(r, "Out-of-Range:%m[^;]", &tmp) == 1) {
+              errorOutOfRangeM = skipspace(tmp);
+              debug3("%s Out-of-Range: %s [device %d]", __PRETTY_FUNCTION__, *errorOutOfRangeM, tunerM.GetId());
+              }
+           FREE_POINTER(tmp);
+           }
+        else if (strstr(r, "Check-Syntax:")) {
+           char *tmp = NULL;
+           if (sscanf(r, "Check-Syntax:%m[^;]", &tmp) == 1) {
+              errorCheckSyntaxM = skipspace(tmp);
+              debug3("%s Check-Syntax: %s [device %d]", __PRETTY_FUNCTION__, *errorCheckSyntaxM, tunerM.GetId());
+              }
+           FREE_POINTER(tmp);
+           }
+        r = strtok_r(NULL, "\r\n", &s);
+        }
+}
+
 bool cSatipRtsp::ValidateLatestResponse(long *rcP)
 {
   bool result = false;
 
   if (handleM) {
+     char *url = NULL;
      long rc = 0;
      CURLcode res = CURLE_OK;
      SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc);
-     if (rc == 200)
-        result = true;
-     else if (rc != 0) {
-        char *url = NULL;
-        SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
-        error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
-        }
+     switch (rc) {
+       case 200:
+            result = true;
+            break;
+       case 400:
+            // SETUP PLAY TEARDOWN
+            // The message body of the response may contain the "Check-Syntax:" parameter followed
+            // by the malformed syntax
+            if (!isempty(*errorCheckSyntaxM)) {
+               SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
+               error("Check syntax: %s (error code %ld: %s) [device %d]", *errorCheckSyntaxM, rc, url, tunerM.GetId());
+               break;
+               }
+       case 403:
+            // SETUP PLAY TEARDOWN
+            // The message body of the response may contain the "Out-of-Range:" parameter followed
+            // by a space-separated list of the attribute names that are not understood:
+            // "src" "fe" "freq" "pol" "msys" "mtype" "plts" "ro" "sr" "fec" "pids" "addpids" "delpids" "mcast
+            if (!isempty(*errorOutOfRangeM)) {
+               SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
+               error("Out of range: %s (error code %ld: %s) [device %d]", *errorOutOfRangeM, rc, url, tunerM.GetId());
+               break;
+               }
+       case 503:
+            // SETUP PLAY
+            // The message body of the response may contain the "No-More:" parameter followed
+            // by a space-separated list of the missing ressources: “sessions” "frontends" "pids
+            if (!isempty(*errorNoMoreM)) {
+               SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
+               error("No more: %s (error code %ld: %s) [device %d]", *errorNoMoreM, rc, url, tunerM.GetId());
+               break;
+               }
+       default:
+            SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_EFFECTIVE_URL, &url);
+            error("Detected invalid status code %ld: %s [device %d]", rc, url, tunerM.GetId());
+            break;
+       }
      if (rcP)
         *rcP = rc;
      }
+  errorNoMoreM = "";
+  errorOutOfRangeM = "";
+  errorCheckSyntaxM = "";
   debug1("%s result=%s [device %d]", __PRETTY_FUNCTION__, result ? "ok" : "failed", tunerM.GetId());
 
   return result;
diff --git a/rtsp.h b/rtsp.h
index 1d1be4d..3949524 100644
--- a/rtsp.h
+++ b/rtsp.h
@@ -15,12 +15,13 @@
 #error "libcurl is missing required RTSP support"
 #endif
 
+#include "common.h"
 #include "tunerif.h"
 
 class cSatipRtsp {
 private:
-  static size_t HeaderCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
-  static size_t WriteCallback(void *ptrP, size_t sizeP, size_t nmembP, void *dataP);
+  static size_t HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
+  static size_t DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP);
   static int    DebugCallback(CURL *handleP, curl_infotype typeP, char *dataP, size_t sizeP, void *userPtrP);
 
   enum {
@@ -29,12 +30,19 @@ private:
   enum eCommunicationMode { cmUnicast, cmMulticast };
 
   cSatipTunerIf &tunerM;
+  cSatipMemoryBuffer headerBufferM;
+  cSatipMemoryBuffer dataBufferM;
   eCommunicationMode modeM;
   CURL *handleM;
   struct curl_slist *headerListM;
+  cString errorNoMoreM;
+  cString errorOutOfRangeM;
+  cString errorCheckSyntaxM;
 
   void Create(void);
   void Destroy(void);
+  void ParseHeader(void);
+  void ParseData(void);
   bool ValidateLatestResponse(long *rcP);
 
   // to prevent copy constructor and assignment
diff --git a/satip.c b/satip.c
index b34da79..6b58e72 100644
--- a/satip.c
+++ b/satip.c
@@ -27,7 +27,7 @@
 #define GITVERSION ""
 #endif
 
-       const char VERSION[]     = "2.2.0" GITVERSION;
+       const char VERSION[]     = "2.2.1" GITVERSION;
 static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
 
 class cPluginSatip : public cPlugin {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-satip.git



More information about the pkg-vdr-dvb-changes mailing list