diff --git a/common.h b/common.h index c85404b..c5e3af0 100644 --- a/common.h +++ b/common.h @@ -13,6 +13,8 @@ #include #include +#define SATIP_DEFAULT_RTSP_PORT 554 + #define SATIP_MAX_DEVICES MAXDEVICES #define SATIP_BUFFER_SIZE KILOBYTE(1024) diff --git a/discover.c b/discover.c index 990af68..a559e85 100644 --- a/discover.c +++ b/discover.c @@ -32,7 +32,7 @@ bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP) if (instanceS) { if (serversP) { for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s)) - instanceS->AddServer(s->IpAddress(), s->Model(), s->Description()); + instanceS->AddServer(s->IpAddress(), s->IpPort(), s->Model(), s->Description()); } else instanceS->Activate(); @@ -47,6 +47,18 @@ void cSatipDiscover::Destroy(void) instanceS->Deactivate(); } +size_t cSatipDiscover::HeaderCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP) +{ + cSatipDiscover *obj = reinterpret_cast(dataP); + size_t len = sizeP * nmembP; + debug16("%s len=%zu", __PRETTY_FUNCTION__, len); + + if (obj && (len > 0)) + obj->headerBufferM.Add(ptrP, len); + + return len; +} + size_t cSatipDiscover::DataCallback(char *ptrP, size_t sizeP, size_t nmembP, void *dataP) { cSatipDiscover *obj = reinterpret_cast(dataP); @@ -91,6 +103,7 @@ int cSatipDiscover::DebugCallback(CURL *handleP, curl_infotype typeP, char *data cSatipDiscover::cSatipDiscover() : cThread("SATIP discover"), mutexM(), + headerBufferM(), dataBufferM(), msearchM(*this), probeUrlListM(), @@ -176,7 +189,9 @@ void cSatipDiscover::Fetch(const char *urlP) SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGFUNCTION, cSatipDiscover::DebugCallback); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_DEBUGDATA, this); - // Set callback + // Set header and data callbacks + SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_HEADERFUNCTION, cSatipDiscover::HeaderCallback); + SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEHEADER, this); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEFUNCTION, cSatipDiscover::DataCallback); SATIP_CURL_EASY_SETOPT(handleM, CURLOPT_WRITEDATA, this); @@ -199,7 +214,8 @@ void cSatipDiscover::Fetch(const char *urlP) SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_RESPONSE_CODE, &rc); SATIP_CURL_EASY_GETINFO(handleM, CURLINFO_PRIMARY_IP, &addr); if (rc == 200) { - ParseDeviceInfo(addr); + ParseDeviceInfo(addr, ParseRtspPort()); + headerBufferM.Reset(); dataBufferM.Reset(); } else @@ -207,9 +223,32 @@ void cSatipDiscover::Fetch(const char *urlP) } } -void cSatipDiscover::ParseDeviceInfo(const char *addrP) +int cSatipDiscover::ParseRtspPort(void) { - debug1("%s (%s)", __PRETTY_FUNCTION__, addrP); + debug1("%s", __PRETTY_FUNCTION__); + char *s, *p = headerBufferM.Data(); + char *r = strtok_r(p, "\r\n", &s); + int port = SATIP_DEFAULT_RTSP_PORT; + + while (r) { + debug16("%s (%zu): %s", __PRETTY_FUNCTION__, headerBufferM.Size(), r); + r = skipspace(r); + if (strstr(r, "X-SATIP-RTSP-Port")) { + int tmp = -1; + if (sscanf(r, "X-SATIP-RTSP-Port:%11d", &tmp) == 1) { + port = tmp; + break; + } + } + r = strtok_r(NULL, "\r\n", &s); + } + + return port; +} + +void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP) +{ + debug1("%s (%s, %d)", __PRETTY_FUNCTION__, addrP, portP); const char *desc = NULL, *model = NULL; #ifdef USE_TINYXML TiXmlDocument doc; @@ -232,12 +271,12 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP) model = modelNode.text().as_string("DVBS2-1"); } #endif - AddServer(addrP, model, desc); + AddServer(addrP, portP, model, desc); } -void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char * descP) +void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char * descP) { - debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP); + debug1("%s (%s, %d, %s, %s)", __PRETTY_FUNCTION__, addrP, portP, modelP, descP); cMutexLock MutexLock(&mutexM); if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) { int n = 0; @@ -246,7 +285,7 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char while (r) { r = skipspace(r); cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++); - cSatipServer *tmp = new cSatipServer(addrP, r, desc); + cSatipServer *tmp = new cSatipServer(addrP, portP, r, desc); if (!serversM.Update(tmp)) { info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); serversM.Add(tmp); @@ -258,7 +297,7 @@ void cSatipDiscover::AddServer(const char *addrP, const char *modelP, const char FREE_POINTER(p); } else { - cSatipServer *tmp = new cSatipServer(addrP, modelP, descP); + cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, descP); if (!serversM.Update(tmp)) { info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); serversM.Add(tmp); @@ -352,6 +391,13 @@ cString cSatipDiscover::GetServerAddress(cSatipServer *serverP) return serversM.GetAddress(serverP); } +int cSatipDiscover::GetServerPort(cSatipServer *serverP) +{ + debug16("%s", __PRETTY_FUNCTION__); + cMutexLock MutexLock(&mutexM); + return serversM.GetPort(serverP); +} + int cSatipDiscover::NumProvidedSystems(void) { debug16("%s", __PRETTY_FUNCTION__); diff --git a/discover.h b/discover.h index 5942e42..ff38b61 100644 --- a/discover.h +++ b/discover.h @@ -21,14 +21,16 @@ class cSatipDiscoverServer : public cListObject { private: + int ipPortM; cString ipAddressM; cString descriptionM; cString modelM; public: - cSatipDiscoverServer(const char *ipAddressP, const char *modelP, const char *descriptionP) + cSatipDiscoverServer(const char *ipAddressP, const int ipPortP, const char *modelP, const char *descriptionP) { - ipAddressM = ipAddressP; modelM = modelP; descriptionM = descriptionP; + ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; descriptionM = descriptionP; } + int IpPort(void) { return ipPortM; } const char *IpAddress(void) { return *ipAddressM; } const char *Model(void) { return *modelM; } const char *Description(void) { return *descriptionM; } @@ -47,9 +49,11 @@ private: eCleanupTimeoutMs = 124000 // in milliseoonds }; static cSatipDiscover *instanceS; + 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); cMutex mutexM; + cSatipMemoryBuffer headerBufferM; cSatipMemoryBuffer dataBufferM; cSatipMsearch msearchM; cStringList probeUrlListM; @@ -59,8 +63,9 @@ 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); + int ParseRtspPort(void); + void ParseDeviceInfo(const char *addrP, const int portP); + void AddServer(const char *addrP, const int portP, const char *modelP, const char *descP); void Fetch(const char *urlP); // constructor cSatipDiscover(); @@ -88,6 +93,7 @@ public: bool IsServerQuirk(cSatipServer *serverP, int quirkP); bool HasServerCI(cSatipServer *serverP); cString GetServerAddress(cSatipServer *serverP); + int GetServerPort(cSatipServer *serverP); cString GetServerList(void); int NumProvidedSystems(void); diff --git a/satip.c b/satip.c index 0228e0b..7ef2a86 100644 --- a/satip.c +++ b/satip.c @@ -84,7 +84,7 @@ const char *cPluginSatip::CommandLineHelp(void) // Return a string that describes all known command line options. return " -d , --devices= set number of devices to be created\n" " -t , --trace= set the tracing mode\n" - " -s ||, --server=||;||\n" + " -s ||, --server=||;||\n" " 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" @@ -233,6 +233,7 @@ void cPluginSatip::ParseServer(const char *paramP) r = skipspace(r); debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r); cString serverAddr, serverModel, serverDescription; + int serverPort = SATIP_DEFAULT_RTSP_PORT; int n2 = 0; char *s2, *p2 = r; char *r2 = strtok_r(p2, "|", &s2); @@ -240,7 +241,14 @@ void cPluginSatip::ParseServer(const char *paramP) debug3("%s param[%d]=%s", __PRETTY_FUNCTION__, n2, r2); switch (n2++) { case 0: + { serverAddr = r2; + char *r3 = strchr(r2, ':'); + if (r3) { + serverPort = strtol(r3 + 1, NULL, 0); + serverAddr = serverAddr.Truncate(r3 - r2); + } + } break; case 1: serverModel = r2; @@ -254,10 +262,10 @@ void cPluginSatip::ParseServer(const char *paramP) r2 = strtok_r(NULL, "|", &s2); } if (*serverAddr && *serverModel && *serverDescription) { - debug1("%s ipaddr=%s model=%s desc=%s", __PRETTY_FUNCTION__, *serverAddr, *serverModel, *serverDescription); + debug1("%s ipaddr=%s port=%d model=%s desc=%s", __PRETTY_FUNCTION__, *serverAddr, serverPort, *serverModel, *serverDescription); if (!serversM) serversM = new cSatipDiscoverServers(); - serversM->Add(new cSatipDiscoverServer(*serverAddr, *serverModel, *serverDescription)); + serversM->Add(new cSatipDiscoverServer(*serverAddr, serverPort, *serverModel, *serverDescription)); } ++n; r = strtok_r(NULL, ";", &s); diff --git a/server.c b/server.c index b732b3b..6506249 100644 --- a/server.c +++ b/server.c @@ -80,11 +80,12 @@ bool cSatipFrontends::Detach(int deviceIdP, int transponderP) // --- cSatipServer ----------------------------------------------------------- -cSatipServer::cSatipServer(const char *addressP, const char *modelP, const char *descriptionP) +cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *descriptionP) : addressM((addressP && *addressP) ? addressP : "0.0.0.0"), modelM((modelP && *modelP) ? modelP : "DVBS-1"), descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"), quirksM(""), + portM(portP), quirkM(eSatipQuirkNone), hasCiM(false), createdM(time(NULL)), @@ -374,6 +375,18 @@ cString cSatipServers::GetAddress(cSatipServer *serverP) return address; } +int cSatipServers::GetPort(cSatipServer *serverP) +{ + int port = SATIP_DEFAULT_RTSP_PORT; + for (cSatipServer *s = First(); s; s = Next(s)) { + if (s == serverP) { + port = s->Port(); + break; + } + } + return port; +} + cString cSatipServers::GetString(cSatipServer *serverP) { cString list = ""; diff --git a/server.h b/server.h index 45bb1df..cdccd3a 100644 --- a/server.h +++ b/server.h @@ -59,6 +59,7 @@ private: cString descriptionM; cString quirksM; cSatipFrontends frontendsM[eSatipFrontendCount]; + int portM; int quirkM; bool hasCiM; time_t createdM; @@ -72,7 +73,7 @@ public: eSatipQuirkForceLock = 0x04, eSatipQuirkMask = 0x0F }; - cSatipServer(const char *addressP, const char *modelP, const char *descriptionP); + cSatipServer(const char *addressP, const int portP, const char *modelP, const char *descriptionP); virtual ~cSatipServer(); virtual int Compare(const cListObject &listObjectP) const; bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP); @@ -89,6 +90,7 @@ public: const char *Model(void) { return *modelM; } const char *Description(void) { return *descriptionM; } const char *Quirks(void) { return *quirksM; } + int Port(void) { return portM; } bool Quirk(int quirkP) { return ((quirkP & eSatipQuirkMask) & quirkM); } bool HasQuirk(void) { return (quirkM != eSatipQuirkNone); } bool HasCI(void) { return hasCiM; } @@ -112,6 +114,7 @@ public: void Cleanup(uint64_t intervalMsP = 0); cString GetAddress(cSatipServer *serverP); cString GetString(cSatipServer *serverP); + int GetPort(cSatipServer *serverP); cString List(void); int NumProvidedSystems(void); }; diff --git a/tuner.c b/tuner.c index fc47b51..a475cd8 100644 --- a/tuner.c +++ b/tuner.c @@ -25,6 +25,7 @@ cSatipTuner::cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP) rtcpM(*this), streamAddrM(""), streamParamM(""), + streamPortM(SATIP_DEFAULT_RTSP_PORT), currentServerM(NULL, deviceP.GetId(), 0), nextServerM(NULL, deviceP.GetId(), 0), mutexM(), @@ -208,7 +209,7 @@ bool cSatipTuner::Connect(void) debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); if (!isempty(*streamAddrM)) { - cString connectionUri = cString::sprintf("rtsp://%s/", *streamAddrM); + cString connectionUri = GetBaseUrl(*streamAddrM, streamPortM); // Just retune if (streamIdM >= 0) { cString uri = cString::sprintf("%sstream=%d?%s", *connectionUri, streamIdM, *streamParamM); @@ -247,7 +248,7 @@ bool cSatipTuner::Disconnect(void) debug1("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); if (!isempty(*streamAddrM) && (streamIdM >= 0)) { - cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM); + cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM); rtspM.Teardown(*uri); // some devices requires a teardown for TCP connection also rtspM.Reset(); @@ -362,6 +363,16 @@ void cSatipTuner::SetSessionTimeout(const char *sessionP, int timeoutP) timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : eMinKeepAliveIntervalMs; } +cString cSatipTuner::GetBaseUrl(const char *addressP, const int portP) +{ + debug16("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, addressP, portP, deviceIdM); + + if (portP != SATIP_DEFAULT_RTSP_PORT) + return cString::sprintf("rtsp://%s:%d/", addressP, portP); + + return cString::sprintf("rtsp://%s/", addressP); +} + int cSatipTuner::GetId(void) { debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); @@ -378,6 +389,7 @@ bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, const // Update stream address and parameter streamAddrM = rtspM.RtspUnescapeString(*nextServerM.GetAddress()); streamParamM = rtspM.RtspUnescapeString(parameterP); + streamPortM = nextServerM.GetPort(); // Reconnect RequestState(tsSet, smExternal); } @@ -416,7 +428,7 @@ bool cSatipTuner::UpdatePids(bool forceP) cMutexLock MutexLock(&mutexM); if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && (addPidsM.Size() || delPidsM.Size()))) && !isempty(*streamAddrM) && (streamIdM > 0)) { - cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM); + cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM); bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI()); bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids); if (forceP || usedummy) { @@ -466,7 +478,7 @@ bool cSatipTuner::KeepAlive(bool forceP) forceP = true; } if (forceP && !isempty(*streamAddrM)) { - cString uri = cString::sprintf("rtsp://%s/", *streamAddrM); + cString uri = GetBaseUrl(*streamAddrM, streamPortM); if (!rtspM.Options(*uri)) return false; } @@ -483,7 +495,7 @@ bool cSatipTuner::ReadReceptionStatus(bool forceP) forceP = true; } if (forceP && !isempty(*streamAddrM) && (streamIdM > 0)) { - cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, streamIdM); + cString uri = cString::sprintf("%sstream=%d", *GetBaseUrl(*streamAddrM, streamPortM), streamIdM); if (rtspM.Describe(*uri)) return true; } @@ -618,5 +630,5 @@ cString cSatipTuner::GetSignalStatus(void) cString cSatipTuner::GetInformation(void) { debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM); - return (currentStateM >= tsTuned) ? cString::sprintf("rtsp://%s/?%s [stream=%d]", *streamAddrM, *streamParamM, streamIdM) : "connection failed"; + return (currentStateM >= tsTuned) ? cString::sprintf("%s?%s [stream=%d]", *GetBaseUrl(*streamAddrM, streamPortM), *streamParamM, streamIdM) : "connection failed"; } diff --git a/tuner.h b/tuner.h index 1c7f655..6c7c952 100644 --- a/tuner.h +++ b/tuner.h @@ -69,6 +69,7 @@ public: void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; transponderM = transponderP; } void Reset(void) { serverM = NULL; transponderM = 0; } cString GetAddress(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; } + int GetPort(void) { return serverM ? cSatipDiscover::GetInstance()->GetServerPort(serverM) : SATIP_DEFAULT_RTSP_PORT; } cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); } }; @@ -98,6 +99,7 @@ private: cSatipRtcp rtcpM; cString streamAddrM; cString streamParamM; + int streamPortM; cSatipTunerServer currentServerM; cSatipTunerServer nextServerM; cMutex mutexM; @@ -130,6 +132,7 @@ private: bool RequestState(eTunerState stateP, eStateMode modeP); const char *StateModeString(eStateMode modeP); const char *TunerStateString(eTunerState stateP); + cString GetBaseUrl(const char *addressP, const int portP); protected: virtual void Action(void);