packages/multimedia/gerbera/patches/010-npupnp.patch
Rosen Penev 65fbf39e2c
gerbera: update to 1.6.1
Removed upstream ffmpeg backport.

Updated npupnp patch with latest upstream version.

Enabled CURL since it's needed for libnpupnp anyway.

Fixed up GCC filesystem CMake variables to be more accurate.

Removed npupnp include hack since it was properly fixed now.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-09-03 14:48:29 -07:00

501 lines
18 KiB
Diff

From a13f3588f78e9ffda5e915f44cbf1957f12513c4 Mon Sep 17 00:00:00 2001
From: Jean-Francois Dockes <jf@dockes.org>
Date: Fri, 13 Mar 2020 09:19:04 +0100
Subject: [PATCH] Quick changes for working with NPUPNP
(Rebased and made default)
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
CMakeLists.txt | 43 +++++++++++++++++-------
src/action_request.cc | 11 +++++-
src/device_description_handler.cc | 4 +++
src/file_request_handler.cc | 4 +++
src/iohandler/file_io_handler.cc | 1 -
src/iohandler/io_handler.cc | 1 -
src/iohandler/mem_io_handler.cc | 1 -
src/serve_request_handler.cc | 8 +++++
src/server.cc | 8 +++++
src/transcoding/transcode_ext_handler.cc | 1 -
src/upnp_cds.cc | 11 ++++++
src/upnp_cm.cc | 11 ++++++
src/upnp_mrreg.cc | 7 +++-
src/url_request_handler.cc | 5 ++-
src/util/upnp_clients.cc | 12 +++++++
src/util/upnp_headers.cc | 12 +++++++
src/web/web_request_handler.cc | 4 +++
17 files changed, 124 insertions(+), 20 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b6db993..b23dad57 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,7 @@ if (CONAN_EXPORTED)
endif()
set(CMAKE_VERBOSE_MAKEFILE off CACHE BOOL "Show verbose build commands")
+set(WITH_NPUPNP 0 CACHE BOOL "Use npupnp instead of pupnp")
set(WITH_MAGIC 1 CACHE BOOL "Use libmagic to identify file mime types")
set(WITH_MYSQL 0 CACHE BOOL "Store media information in MySQL DB")
set(WITH_CURL 1 CACHE BOOL "CURL required for online services")
@@ -303,23 +304,39 @@ add_definitions(${LFS_DEFINITIONS})
add_compile_options(${LFS_COMPILE_OPTIONS})
target_link_libraries(libgerbera ${LFS_LIBRARIES})
-find_package (pupnp "1.12.1" REQUIRED)
+if (WITH_NPUPNP)
+ find_package(PkgConfig QUIET)
+ pkg_check_modules (NPUPNP QUIET libnpupnp>=4.0.11)
+ if (NOT NPUPNP_FOUND)
+ find_package (NPUPNP REQUIRED)
+ endif()
+ if (NPUPNP_FOUND)
+ include_directories (${NPUPNP_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES npupnp)
+ add_definitions(-DUSING_NPUPNP)
+ target_link_libraries (libgerbera ${NPUPNP_LIBRARIES})
+ else()
+ message(FATAL_ERROR "libnpupnp not found")
+ endif()
+else()
+ find_package (pupnp "1.12.1" REQUIRED)
-set(CMAKE_REQUIRED_LIBRARIES pupnp::pupnp)
+ set(CMAKE_REQUIRED_LIBRARIES pupnp::pupnp)
-check_cxx_symbol_exists(UPNP_ENABLE_IPV6 "upnpconfig.h" UPNP_HAS_IPV6)
-if (NOT UPNP_HAS_IPV6)
- message(FATAL_ERROR "Gerbera requires libupnp with IPv6 support.")
-endif()
+ check_cxx_symbol_exists(UPNP_ENABLE_IPV6 "upnpconfig.h" UPNP_HAS_IPV6)
+ if (NOT UPNP_HAS_IPV6)
+ message(FATAL_ERROR "Gerbera requires libupnp with IPv6 support.")
+ endif()
-check_cxx_symbol_exists(UPNP_MINISERVER_REUSEADDR "upnpconfig.h" UPNP_HAS_REUSEADDR)
-if (NOT UPNP_HAS_REUSEADDR)
- message(WARNING [=[
-!! It is strongly recommended to build libupnp with --enable-reuseaddr !!
-Without this option Gerbera will be unable to restart with the same port number.]=])
-endif()
+ check_cxx_symbol_exists(UPNP_MINISERVER_REUSEADDR "upnpconfig.h" UPNP_HAS_REUSEADDR)
+ if (NOT UPNP_HAS_REUSEADDR)
+ message(WARNING [=[
+ !! It is strongly recommended to build libupnp with --enable-reuseaddr !!
+ Without this option Gerbera will be unable to restart with the same port number.]=])
+ endif()
-target_link_libraries (libgerbera pupnp::pupnp)
+ target_link_libraries (libgerbera pupnp::pupnp)
+endif()
find_package(fmt REQUIRED)
target_link_libraries(libgerbera fmt::fmt)
diff --git a/src/action_request.cc b/src/action_request.cc
index fab0e910..5677e61e 100644
--- a/src/action_request.cc
+++ b/src/action_request.cc
@@ -65,10 +65,14 @@ std::string ActionRequest::getServiceID() const
std::unique_ptr<pugi::xml_document> ActionRequest::getRequest() const
{
- DOMString cxml = ixmlPrintDocument(UpnpActionRequest_get_ActionRequest(upnp_request));
auto request = std::make_unique<pugi::xml_document>();
+#if defined(USING_NPUPNP)
+ auto ret = request->load_string(upnp_request->xmlAction.c_str());
+#else
+ DOMString cxml = ixmlPrintDocument(UpnpActionRequest_get_ActionRequest(upnp_request));
auto ret = request->load_string(cxml);
ixmlFreeDOMString(cxml);
+#endif
if (ret.status != pugi::xml_parse_status::status_ok)
throw_std_runtime_error("Unable to parse ixml");
@@ -94,6 +98,10 @@ void ActionRequest::update()
std::string xml = buf.str();
log_debug("ActionRequest::update(): {}", xml.c_str());
+#if defined(USING_NPUPNP)
+ UpnpActionRequest_set_xmlResponse(upnp_request, xml);
+ UpnpActionRequest_set_ErrCode(upnp_request, errCode);
+#else
IXML_Document* result = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &result);
@@ -105,6 +113,7 @@ void ActionRequest::update()
UpnpActionRequest_set_ActionResult(upnp_request, result);
UpnpActionRequest_set_ErrCode(upnp_request, errCode);
}
+#endif
} else {
// ok, here there can be two cases
// either the function below already did set an error code,
diff --git a/src/device_description_handler.cc b/src/device_description_handler.cc
index 6aca745e..cf2e8015 100644
--- a/src/device_description_handler.cc
+++ b/src/device_description_handler.cc
@@ -45,7 +45,11 @@ void DeviceDescriptionHandler::getInfo(const char* filename, UpnpFileInfo* info)
{
// We should be able to do the generation here, but libupnp doesnt support the request cookies yet
UpnpFileInfo_set_FileLength(info, -1);
+#if defined(USING_NPUPNP)
UpnpFileInfo_set_ContentType(info, "application/xml");
+#else
+ UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString("application/xml"));
+#endif
UpnpFileInfo_set_IsReadable(info, 1);
UpnpFileInfo_set_IsDirectory(info, 0);
}
diff --git a/src/file_request_handler.cc b/src/file_request_handler.cc
index cfa3eaed..915e411b 100644
--- a/src/file_request_handler.cc
+++ b/src/file_request_handler.cc
@@ -238,7 +238,11 @@ void FileRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
UpnpFileInfo_set_LastModified(info, statbuf.st_mtime);
UpnpFileInfo_set_IsDirectory(info, S_ISDIR(statbuf.st_mode));
+#if defined(USING_NPUPNP)
+ UpnpFileInfo_set_ContentType(info, mimeType);
+#else
UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str()));
+#endif
headers->writeHeaders(info);
diff --git a/src/iohandler/file_io_handler.cc b/src/iohandler/file_io_handler.cc
index 7e239250..b023e85b 100644
--- a/src/iohandler/file_io_handler.cc
+++ b/src/iohandler/file_io_handler.cc
@@ -32,7 +32,6 @@
#include "file_io_handler.h" // API
#include <cstdio>
-#include <ixml.h>
#include <utility>
#include "cds_objects.h"
diff --git a/src/iohandler/io_handler.cc b/src/iohandler/io_handler.cc
index f9789425..1153ce6b 100644
--- a/src/iohandler/io_handler.cc
+++ b/src/iohandler/io_handler.cc
@@ -31,7 +31,6 @@
#include "io_handler.h" // API
-#include <ixml.h>
#include <unistd.h>
#include "server.h"
diff --git a/src/iohandler/mem_io_handler.cc b/src/iohandler/mem_io_handler.cc
index 5574a16d..223746ef 100644
--- a/src/iohandler/mem_io_handler.cc
+++ b/src/iohandler/mem_io_handler.cc
@@ -35,7 +35,6 @@
#include <cstdlib>
#include <cstring>
#include <ctime>
-#include <ixml.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/src/serve_request_handler.cc b/src/serve_request_handler.cc
index 59f37252..42d07e94 100644
--- a/src/serve_request_handler.cc
+++ b/src/serve_request_handler.cc
@@ -94,7 +94,11 @@ void ServeRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
UpnpFileInfo_set_IsReadable(info, 0);
}
+#if defined(USING_NPUPNP)
+ UpnpFileInfo_set_ContentType(info, mimetype);
+#else
UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimetype.c_str()));
+#endif
} else {
throw_std_runtime_error("Not a regular file: " + path);
}
@@ -158,7 +162,11 @@ std::unique_ptr<IOHandler> ServeRequestHandler::open(const char* filename,
}
+#if defined(USING_NPUPNP)
+ info->content_type = mimetype;
+#else
info->content_type = ixmlCloneDOMString(mimetype.c_str());
+#endif
*/
} else {
throw_std_runtime_error("Not a regular file: " + path);
diff --git a/src/server.cc b/src/server.cc
index a83c28cd..d4ce3e51 100644
--- a/src/server.cc
+++ b/src/server.cc
@@ -393,9 +393,17 @@ int Server::handleUpnpClientEvent(Upnp_EventType eventType, const void* event)
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
case UPNP_DISCOVERY_SEARCH_RESULT: {
auto d_event = reinterpret_cast<const UpnpDiscovery*>(event);
+#if defined(USING_NPUPNP)
+ const char* userAgent = UpnpDiscovery_get_Os_cstr(d_event);
+#else
const char* userAgent = UpnpString_get_String(UpnpDiscovery_get_Os(d_event));
+#endif
const struct sockaddr_storage* destAddr = UpnpDiscovery_get_DestAddr(d_event);
+#if defined(USING_NPUPNP)
+ const char* location = UpnpDiscovery_get_Location_cstr(d_event);
+#else
const char* location = UpnpString_get_String(UpnpDiscovery_get_Location(d_event));
+#endif
Clients::addClientByDiscovery(destAddr, userAgent, location);
break;
diff --git a/src/transcoding/transcode_ext_handler.cc b/src/transcoding/transcode_ext_handler.cc
index 67ee79d9..1da59ea2 100644
--- a/src/transcoding/transcode_ext_handler.cc
+++ b/src/transcoding/transcode_ext_handler.cc
@@ -37,7 +37,6 @@
#include <cstring>
#include <fcntl.h>
#include <filesystem>
-#include <ixml.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
diff --git a/src/upnp_cds.cc b/src/upnp_cds.cc
index 12ffeea2..5c2e1043 100644
--- a/src/upnp_cds.cc
+++ b/src/upnp_cds.cc
@@ -284,6 +284,11 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptr<S
propset->print(buf, "", 0);
std::string xml = buf.str();
+#if defined(USING_NPUPNP)
+ UpnpAcceptSubscriptionXML(
+ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
+ DESC_CDS_SERVICE_ID, xml, request->getSubscriptionID().c_str());
+#else
IXML_Document* event = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &event);
if (err != IXML_SUCCESS) {
@@ -295,6 +300,7 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptr<S
DESC_CDS_SERVICE_ID, event, request->getSubscriptionID().c_str());
ixmlDocument_free(event);
+#endif
log_debug("end");
}
@@ -313,6 +319,10 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe
propset->print(buf, "", 0);
std::string xml = buf.str();
+#if defined(USING_NPUPNP)
+ UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
+ DESC_CDS_SERVICE_ID, xml);
+#else
IXML_Document* event = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &event);
if (err != IXML_SUCCESS) {
@@ -325,6 +335,7 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe
DESC_CDS_SERVICE_ID, event);
ixmlDocument_free(event);
+#endif
log_debug("end");
}
diff --git a/src/upnp_cm.cc b/src/upnp_cm.cc
index aa608480..d7ab40cf 100644
--- a/src/upnp_cm.cc
+++ b/src/upnp_cm.cc
@@ -127,6 +127,11 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr<
propset->print(buf, "", 0);
std::string xml = buf.str();
+#if defined(USING_NPUPNP)
+ UpnpAcceptSubscriptionXML(
+ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
+ DESC_CM_SERVICE_ID, xml, request->getSubscriptionID().c_str());
+#else
IXML_Document* event = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &event);
if (err != IXML_SUCCESS) {
@@ -138,6 +143,7 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr<
DESC_CM_SERVICE_ID, event, request->getSubscriptionID().c_str());
ixmlDocument_free(event);
+#endif
}
void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceProtocol_CSV)
@@ -150,6 +156,10 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP
propset->print(buf, "", 0);
std::string xml = buf.str();
+#if defined(USING_NPUPNP)
+ UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
+ DESC_CM_SERVICE_ID, xml);
+#else
IXML_Document* event = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &event);
if (err != IXML_SUCCESS) {
@@ -162,4 +172,5 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP
DESC_CM_SERVICE_ID, event);
ixmlDocument_free(event);
+#endif
}
diff --git a/src/upnp_mrreg.cc b/src/upnp_mrreg.cc
index 16eefaed..ecb49025 100644
--- a/src/upnp_mrreg.cc
+++ b/src/upnp_mrreg.cc
@@ -34,7 +34,6 @@
#include <utility>
#include "config/config_manager.h"
-#include "ixml.h"
#include "server.h"
#include "storage/storage.h"
#include "upnp_xml.h"
@@ -120,6 +119,11 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptr<Subscr
propset->print(buf, "", 0);
std::string xml = buf.str();
+#if defined(USING_NPUPNP)
+ UpnpAcceptSubscriptionXML(
+ deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
+ DESC_MRREG_SERVICE_ID, xml, request->getSubscriptionID().c_str());
+#else
IXML_Document* event = nullptr;
int err = ixmlParseBufferEx(xml.c_str(), &event);
if (err != IXML_SUCCESS) {
@@ -131,6 +135,7 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptr<Subscr
DESC_MRREG_SERVICE_ID, event, request->getSubscriptionID().c_str());
ixmlDocument_free(event);
+#endif
}
// TODO: FIXME
diff --git a/src/url_request_handler.cc b/src/url_request_handler.cc
index f2a99c94..7de2227d 100644
--- a/src/url_request_handler.cc
+++ b/src/url_request_handler.cc
@@ -32,7 +32,6 @@
#ifdef HAVE_CURL
#include "url_request_handler.h" // API
-#include <ixml.h>
#include <utility>
#include "config/config_manager.h"
@@ -138,7 +137,11 @@ void URLRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
// ixmlCloneDOMString(header.c_str()));
// }
+#if defined(USING_NPUPNP)
+ UpnpFileInfo_set_ContentType(info, mimeType);
+#else
UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str()));
+#endif
log_debug("web_get_info(): end");
/// \todo transcoding for get_info
diff --git a/src/util/upnp_clients.cc b/src/util/upnp_clients.cc
index 6fd40de2..28f0fb16 100644
--- a/src/util/upnp_clients.cc
+++ b/src/util/upnp_clients.cc
@@ -262,6 +262,17 @@ bool Clients::getInfoByType(const std::string& match, ClientMatchType type, cons
bool Clients::downloadDescription(const std::string& location, std::unique_ptr<pugi::xml_document>& xml)
{
+#if defined(USING_NPUPNP)
+ std::string description, ct;
+ int errCode = UpnpDownloadUrlItem(location, description, ct);
+ if (errCode != UPNP_E_SUCCESS) {
+ log_debug("Error obtaining client description from {} -- error = {}", location, errCode);
+ return false;
+ }
+ const char* cxml = description.c_str();
+ xml = std::make_unique<pugi::xml_document>();
+ auto ret = xml->load_string(cxml);
+#else
IXML_Document* descDoc = nullptr;
int errCode = UpnpDownloadXmlDoc(location.c_str(), &descDoc);
if (errCode != UPNP_E_SUCCESS) {
@@ -275,6 +286,7 @@ bool Clients::downloadDescription(const std::string& location, std::unique_ptr<p
ixmlFreeDOMString(cxml);
ixmlDocument_free(descDoc);
+#endif
if (ret.status != pugi::xml_parse_status::status_ok) {
log_debug("Unable to parse xml client description from {}", location);
diff --git a/src/util/upnp_headers.cc b/src/util/upnp_headers.cc
index 6eddedec..b7763444 100644
--- a/src/util/upnp_headers.cc
+++ b/src/util/upnp_headers.cc
@@ -25,11 +25,13 @@
#include "upnp_headers.h" // API
+#if !defined(USING_NPUPNP)
#if (UPNP_VERSION > 11299)
#include <UpnpExtraHeaders.h>
#else
#include <ExtraHeaders.h>
#endif
+#endif
#include <string>
#include "common.h"
@@ -101,18 +103,27 @@ void Headers::writeHeaders(UpnpFileInfo* fileInfo) const
if (headers == nullptr)
return;
+#if defined(USING_NPUPNP)
+ std::copy(headers->begin(), headers->end(), std::back_inserter(fileInfo->response_headers));
+#else
auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
for (const auto& iter : *headers) {
UpnpExtraHeaders* h = UpnpExtraHeaders_new();
UpnpExtraHeaders_set_resp(h, formatHeader(iter, false).c_str());
UpnpListInsert(head, UpnpListEnd(head), const_cast<UpnpListHead*>(UpnpExtraHeaders_get_node(h)));
}
+#endif
}
std::unique_ptr<std::map<std::string, std::string>> Headers::readHeaders(UpnpFileInfo* fileInfo)
{
auto ret = std::make_unique<std::map<std::string, std::string>>();
+#if defined(USING_NPUPNP)
+ for (const auto& entry : fileInfo->request_headers) {
+ ret->insert(entry);
+ }
+#else
auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
UpnpListIter pos;
for (pos = UpnpListBegin(head); pos != UpnpListEnd(head); pos = UpnpListNext(head, pos)) {
@@ -121,6 +132,7 @@ std::unique_ptr<std::map<std::string, std::string>> Headers::readHeaders(UpnpFil
auto add = parseHeader(header);
ret->insert(add);
}
+#endif
return ret;
}
diff --git a/src/web/web_request_handler.cc b/src/web/web_request_handler.cc
index 60e2d028..117dcbfa 100644
--- a/src/web/web_request_handler.cc
+++ b/src/web/web_request_handler.cc
@@ -112,7 +112,11 @@ void WebRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
std::string mimetype = (returnType == "xml") ? MIMETYPE_XML : MIMETYPE_JSON;
std::string contentType = mimetype + "; charset=" + DEFAULT_INTERNAL_CHARSET;
+#if defined(USING_NPUPNP)
+ UpnpFileInfo_set_ContentType(info, contentType);
+#else
UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(contentType.c_str()));
+#endif
Headers headers;
headers.addHeader(std::string { "Cache-Control" }, std::string { "no-cache, must-revalidate" });
headers.writeHeaders(info);