You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

485 lines
17 KiB

  1. From 2ebccbb993dca41674de295f2d513abd568f971a Mon Sep 17 00:00:00 2001
  2. From: Jean-Francois Dockes <jf@dockes.org>
  3. Date: Fri, 13 Mar 2020 09:19:04 +0100
  4. Subject: [PATCH] Quick changes for working with NPUPNP
  5. ---
  6. CMakeLists.txt | 12 +++++-------
  7. src/action_request.cc | 11 +++++++++++
  8. src/device_description_handler.cc | 4 ++++
  9. src/file_request_handler.cc | 4 ++++
  10. src/iohandler/file_io_handler.cc | 2 ++
  11. src/iohandler/io_handler.cc | 2 ++
  12. src/iohandler/mem_io_handler.cc | 2 ++
  13. src/serve_request_handler.cc | 9 ++++++++-
  14. src/server.cc | 8 ++++++++
  15. src/transcoding/transcode_ext_handler.cc | 2 ++
  16. src/upnp_cds.cc | 12 +++++++++++-
  17. src/upnp_cm.cc | 11 +++++++++++
  18. src/upnp_mrreg.cc | 10 +++++++++-
  19. src/url_request_handler.cc | 6 ++++++
  20. src/util/upnp_clients.cc | 12 ++++++++++++
  21. src/util/upnp_headers.cc | 14 +++++++++++++-
  22. src/util/upnp_headers.h | 2 ++
  23. src/web/web_request_handler.cc | 4 ++++
  24. 18 files changed, 116 insertions(+), 11 deletions(-)
  25. diff --git a/CMakeLists.txt b/CMakeLists.txt
  26. index 46f2ca5c..b51300d9 100644
  27. --- a/CMakeLists.txt
  28. +++ b/CMakeLists.txt
  29. @@ -293,13 +293,11 @@ if (LFS_FOUND)
  30. target_link_libraries(gerbera ${LFS_LIBRARIES})
  31. endif()
  32. -find_package (LibUpnp REQUIRED)
  33. -include_directories(${UPNP_INCLUDE_DIRS})
  34. -target_link_libraries (gerbera ${UPNP_LIBRARIES})
  35. -
  36. -if (UPNP_VERSION_STRING VERSION_LESS "1.12.1")
  37. - message(FATAL_ERROR "gerbera requires libupnp 1.12.1 or above.")
  38. -endif()
  39. +#### Hard-coded NPUPNP defs for now, just for testing
  40. +add_definitions(-DUSING_NPUPNP)
  41. +include_directories(/usr/include/npupnp/upnp)
  42. +target_link_libraries (gerbera -lnpupnp)
  43. +set (UPNP_HAS_IPV6 1)
  44. if (NOT UPNP_HAS_IPV6)
  45. message(FATAL_ERROR "Gerbera requires libupnp with IPv6 support.")
  46. diff --git a/src/action_request.cc b/src/action_request.cc
  47. index 3aa4a991..29be6aaf 100644
  48. --- a/src/action_request.cc
  49. +++ b/src/action_request.cc
  50. @@ -65,11 +65,17 @@ std::string ActionRequest::getServiceID() const
  51. std::unique_ptr<pugi::xml_document> ActionRequest::getRequest() const
  52. {
  53. +#if !defined(USING_NPUPNP)
  54. DOMString cxml = ixmlPrintDocument(UpnpActionRequest_get_ActionRequest(upnp_request));
  55. +#endif
  56. auto request = std::make_unique<pugi::xml_document>();
  57. +#if defined(USING_NPUPNP)
  58. + auto ret = request->load_string(upnp_request->xmlAction.c_str());
  59. +#else
  60. auto ret = request->load_string(cxml);
  61. ixmlFreeDOMString(cxml);
  62. +#endif
  63. if (ret.status != pugi::xml_parse_status::status_ok)
  64. throw_std_runtime_error("Unable to parse ixml");
  65. @@ -94,6 +100,7 @@ void ActionRequest::update()
  66. std::string xml = buf.str();
  67. log_debug("ActionRequest::update(): {}", xml.c_str());
  68. +#if !defined(USING_NPUPNP)
  69. IXML_Document* result = nullptr;
  70. int err = ixmlParseBufferEx(xml.c_str(), &result);
  71. @@ -105,6 +112,10 @@ void ActionRequest::update()
  72. UpnpActionRequest_set_ActionResult(upnp_request, result);
  73. UpnpActionRequest_set_ErrCode(upnp_request, errCode);
  74. }
  75. +#else
  76. + UpnpActionRequest_set_xmlResponse(upnp_request, xml);
  77. + UpnpActionRequest_set_ErrCode(upnp_request, errCode);
  78. +#endif
  79. } else {
  80. // ok, here there can be two cases
  81. // either the function below already did set an error code,
  82. diff --git a/src/device_description_handler.cc b/src/device_description_handler.cc
  83. index 6aca745e..cf2e8015 100644
  84. --- a/src/device_description_handler.cc
  85. +++ b/src/device_description_handler.cc
  86. @@ -45,7 +45,11 @@ void DeviceDescriptionHandler::getInfo(const char* filename, UpnpFileInfo* info)
  87. {
  88. // We should be able to do the generation here, but libupnp doesnt support the request cookies yet
  89. UpnpFileInfo_set_FileLength(info, -1);
  90. +#if defined(USING_NPUPNP)
  91. UpnpFileInfo_set_ContentType(info, "application/xml");
  92. +#else
  93. + UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString("application/xml"));
  94. +#endif
  95. UpnpFileInfo_set_IsReadable(info, 1);
  96. UpnpFileInfo_set_IsDirectory(info, 0);
  97. }
  98. diff --git a/src/file_request_handler.cc b/src/file_request_handler.cc
  99. index e8579b06..615f7e85 100644
  100. --- a/src/file_request_handler.cc
  101. +++ b/src/file_request_handler.cc
  102. @@ -238,7 +238,11 @@ void FileRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
  103. UpnpFileInfo_set_LastModified(info, statbuf.st_mtime);
  104. UpnpFileInfo_set_IsDirectory(info, S_ISDIR(statbuf.st_mode));
  105. +#if defined(USING_NPUPNP)
  106. + UpnpFileInfo_set_ContentType(info, mimeType);
  107. +#else
  108. UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str()));
  109. +#endif
  110. headers->writeHeaders(info);
  111. diff --git a/src/iohandler/file_io_handler.cc b/src/iohandler/file_io_handler.cc
  112. index 7e239250..ab5155ec 100644
  113. --- a/src/iohandler/file_io_handler.cc
  114. +++ b/src/iohandler/file_io_handler.cc
  115. @@ -32,7 +32,9 @@
  116. #include "file_io_handler.h" // API
  117. #include <cstdio>
  118. +#ifndef USING_NPUPNP
  119. #include <ixml.h>
  120. +#endif
  121. #include <utility>
  122. #include "cds_objects.h"
  123. diff --git a/src/iohandler/io_handler.cc b/src/iohandler/io_handler.cc
  124. index f9789425..75a36130 100644
  125. --- a/src/iohandler/io_handler.cc
  126. +++ b/src/iohandler/io_handler.cc
  127. @@ -31,7 +31,9 @@
  128. #include "io_handler.h" // API
  129. +#ifndef USING_NPUPNP
  130. #include <ixml.h>
  131. +#endif
  132. #include <unistd.h>
  133. #include "server.h"
  134. diff --git a/src/iohandler/mem_io_handler.cc b/src/iohandler/mem_io_handler.cc
  135. index 5574a16d..2916fd12 100644
  136. --- a/src/iohandler/mem_io_handler.cc
  137. +++ b/src/iohandler/mem_io_handler.cc
  138. @@ -35,7 +35,9 @@
  139. #include <cstdlib>
  140. #include <cstring>
  141. #include <ctime>
  142. +#ifndef USING_NPUPNP
  143. #include <ixml.h>
  144. +#endif
  145. #include <sys/stat.h>
  146. #include <sys/types.h>
  147. #include <unistd.h>
  148. diff --git a/src/serve_request_handler.cc b/src/serve_request_handler.cc
  149. index 8eaf46af..b9bd7b25 100644
  150. --- a/src/serve_request_handler.cc
  151. +++ b/src/serve_request_handler.cc
  152. @@ -94,7 +94,11 @@ void ServeRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
  153. UpnpFileInfo_set_IsReadable(info, 0);
  154. }
  155. +#if defined(USING_NPUPNP)
  156. + UpnpFileInfo_set_ContentType(info, mimetype);
  157. +#else
  158. UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimetype.c_str()));
  159. +#endif
  160. } else {
  161. throw_std_runtime_error("Not a regular file: " + path);
  162. }
  163. @@ -157,8 +161,11 @@ std::unique_ptr<IOHandler> ServeRequestHandler::open(const char* filename,
  164. info->is_readable = 0;
  165. }
  166. -
  167. +#if defined(USING_NPUPNP)
  168. + info->content_type = mimetype;
  169. +#else
  170. info->content_type = ixmlCloneDOMString(mimetype.c_str());
  171. +#endif
  172. */
  173. } else {
  174. throw_std_runtime_error("Not a regular file: " + path);
  175. diff --git a/src/server.cc b/src/server.cc
  176. index 913a4913..7cbabc71 100644
  177. --- a/src/server.cc
  178. +++ b/src/server.cc
  179. @@ -398,9 +398,17 @@ int Server::handleUpnpClientEvent(Upnp_EventType eventType, const void* event)
  180. case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
  181. case UPNP_DISCOVERY_SEARCH_RESULT: {
  182. auto d_event = reinterpret_cast<const UpnpDiscovery*>(event);
  183. +#if defined(USING_NPUPNP)
  184. + const char* userAgent = UpnpDiscovery_get_Os_cstr(d_event);
  185. +#else
  186. const char* userAgent = UpnpString_get_String(UpnpDiscovery_get_Os(d_event));
  187. +#endif
  188. const struct sockaddr_storage* destAddr = UpnpDiscovery_get_DestAddr(d_event);
  189. +#if defined(USING_NPUPNP)
  190. + const char* location = UpnpDiscovery_get_Location_cstr(d_event);
  191. +#else
  192. const char* location = UpnpString_get_String(UpnpDiscovery_get_Location(d_event));
  193. +#endif
  194. Clients::addClientByDiscovery(destAddr, userAgent, location);
  195. break;
  196. diff --git a/src/transcoding/transcode_ext_handler.cc b/src/transcoding/transcode_ext_handler.cc
  197. index 4dad0e3f..412c1370 100644
  198. --- a/src/transcoding/transcode_ext_handler.cc
  199. +++ b/src/transcoding/transcode_ext_handler.cc
  200. @@ -37,7 +37,9 @@
  201. #include <cstring>
  202. #include <fcntl.h>
  203. #include <filesystem>
  204. +#ifndef USING_NPUPNP
  205. #include <ixml.h>
  206. +#endif
  207. #include <sys/stat.h>
  208. #include <sys/types.h>
  209. #include <unistd.h>
  210. diff --git a/src/upnp_cds.cc b/src/upnp_cds.cc
  211. index 6491fa78..a758655c 100644
  212. --- a/src/upnp_cds.cc
  213. +++ b/src/upnp_cds.cc
  214. @@ -284,6 +284,7 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptr<S
  215. propset->print(buf, "", 0);
  216. std::string xml = buf.str();
  217. +#if !defined(USING_NPUPNP)
  218. IXML_Document* event = nullptr;
  219. int err = ixmlParseBufferEx(xml.c_str(), &event);
  220. if (err != IXML_SUCCESS) {
  221. @@ -295,6 +296,11 @@ void ContentDirectoryService::processSubscriptionRequest(const std::unique_ptr<S
  222. DESC_CDS_SERVICE_ID, event, request->getSubscriptionID().c_str());
  223. ixmlDocument_free(event);
  224. +#else
  225. + UpnpAcceptSubscriptionXML(
  226. + deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
  227. + DESC_CDS_SERVICE_ID, xml, request->getSubscriptionID().c_str());
  228. +#endif
  229. log_debug("end");
  230. }
  231. @@ -313,6 +319,7 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe
  232. propset->print(buf, "", 0);
  233. std::string xml = buf.str();
  234. +#if !defined(USING_NPUPNP)
  235. IXML_Document* event = nullptr;
  236. int err = ixmlParseBufferEx(xml.c_str(), &event);
  237. if (err != IXML_SUCCESS) {
  238. @@ -323,8 +330,11 @@ void ContentDirectoryService::sendSubscriptionUpdate(const std::string& containe
  239. UpnpNotifyExt(deviceHandle,
  240. config->getOption(CFG_SERVER_UDN).c_str(),
  241. DESC_CDS_SERVICE_ID, event);
  242. -
  243. ixmlDocument_free(event);
  244. +#else
  245. + UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
  246. + DESC_CDS_SERVICE_ID, xml);
  247. +#endif
  248. log_debug("end");
  249. }
  250. diff --git a/src/upnp_cm.cc b/src/upnp_cm.cc
  251. index aa608480..33f86bd2 100644
  252. --- a/src/upnp_cm.cc
  253. +++ b/src/upnp_cm.cc
  254. @@ -127,6 +127,7 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr<
  255. propset->print(buf, "", 0);
  256. std::string xml = buf.str();
  257. +#if !defined(USING_NPUPNP)
  258. IXML_Document* event = nullptr;
  259. int err = ixmlParseBufferEx(xml.c_str(), &event);
  260. if (err != IXML_SUCCESS) {
  261. @@ -138,6 +139,11 @@ void ConnectionManagerService::processSubscriptionRequest(const std::unique_ptr<
  262. DESC_CM_SERVICE_ID, event, request->getSubscriptionID().c_str());
  263. ixmlDocument_free(event);
  264. +#else
  265. + UpnpAcceptSubscriptionXML(
  266. + deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
  267. + DESC_CM_SERVICE_ID, xml, request->getSubscriptionID().c_str());
  268. +#endif
  269. }
  270. void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceProtocol_CSV)
  271. @@ -150,6 +156,7 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP
  272. propset->print(buf, "", 0);
  273. std::string xml = buf.str();
  274. +#if !defined(USING_NPUPNP)
  275. IXML_Document* event = nullptr;
  276. int err = ixmlParseBufferEx(xml.c_str(), &event);
  277. if (err != IXML_SUCCESS) {
  278. @@ -162,4 +169,8 @@ void ConnectionManagerService::sendSubscriptionUpdate(const std::string& sourceP
  279. DESC_CM_SERVICE_ID, event);
  280. ixmlDocument_free(event);
  281. +#else
  282. + UpnpNotifyXML(deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
  283. + DESC_CM_SERVICE_ID, xml);
  284. +#endif
  285. }
  286. diff --git a/src/upnp_mrreg.cc b/src/upnp_mrreg.cc
  287. index 16eefaed..f993f452 100644
  288. --- a/src/upnp_mrreg.cc
  289. +++ b/src/upnp_mrreg.cc
  290. @@ -34,7 +34,9 @@
  291. #include <utility>
  292. #include "config/config_manager.h"
  293. -#include "ixml.h"
  294. +#ifndef USING_NPUPNP
  295. +#include <ixml.h>
  296. +#endif
  297. #include "server.h"
  298. #include "storage/storage.h"
  299. #include "upnp_xml.h"
  300. @@ -120,6 +122,7 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptr<Subscr
  301. propset->print(buf, "", 0);
  302. std::string xml = buf.str();
  303. +#if !defined(USING_NPUPNP)
  304. IXML_Document* event = nullptr;
  305. int err = ixmlParseBufferEx(xml.c_str(), &event);
  306. if (err != IXML_SUCCESS) {
  307. @@ -131,6 +134,11 @@ void MRRegistrarService::processSubscriptionRequest(const std::unique_ptr<Subscr
  308. DESC_MRREG_SERVICE_ID, event, request->getSubscriptionID().c_str());
  309. ixmlDocument_free(event);
  310. +#else
  311. + UpnpAcceptSubscriptionXML(
  312. + deviceHandle, config->getOption(CFG_SERVER_UDN).c_str(),
  313. + DESC_MRREG_SERVICE_ID, xml, request->getSubscriptionID().c_str());
  314. +#endif
  315. }
  316. // TODO: FIXME
  317. diff --git a/src/url_request_handler.cc b/src/url_request_handler.cc
  318. index f2a99c94..66af027b 100644
  319. --- a/src/url_request_handler.cc
  320. +++ b/src/url_request_handler.cc
  321. @@ -32,7 +32,9 @@
  322. #ifdef HAVE_CURL
  323. #include "url_request_handler.h" // API
  324. +#ifndef USING_NPUPNP
  325. #include <ixml.h>
  326. +#endif
  327. #include <utility>
  328. #include "config/config_manager.h"
  329. @@ -138,7 +140,11 @@ void URLRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
  330. // ixmlCloneDOMString(header.c_str()));
  331. // }
  332. +#if defined(USING_NPUPNP)
  333. + UpnpFileInfo_set_ContentType(info, mimeType);
  334. +#else
  335. UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(mimeType.c_str()));
  336. +#endif
  337. log_debug("web_get_info(): end");
  338. /// \todo transcoding for get_info
  339. diff --git a/src/util/upnp_clients.cc b/src/util/upnp_clients.cc
  340. index ab02b58d..7bc85d77 100644
  341. --- a/src/util/upnp_clients.cc
  342. +++ b/src/util/upnp_clients.cc
  343. @@ -203,6 +203,15 @@ bool Clients::getInfoByType(const std::string& match, ClientMatchType type, cons
  344. bool Clients::downloadDescription(const std::string& location, std::unique_ptr<pugi::xml_document>& xml)
  345. {
  346. +#if defined(USING_NPUPNP)
  347. + std::string description, ct;
  348. + int errCode = UpnpDownloadUrlItem(location, description, ct);
  349. + if (errCode != UPNP_E_SUCCESS) {
  350. + log_debug("Error obtaining client description from {} -- error = {}", location, errCode);
  351. + return false;
  352. + }
  353. + const char *cxml = description.c_str();
  354. +#else
  355. IXML_Document* descDoc = nullptr;
  356. int errCode = UpnpDownloadXmlDoc(location.c_str(), &descDoc);
  357. if (errCode != UPNP_E_SUCCESS) {
  358. @@ -211,12 +220,15 @@ bool Clients::downloadDescription(const std::string& location, std::unique_ptr<p
  359. }
  360. DOMString cxml = ixmlPrintDocument(descDoc);
  361. +#endif
  362. xml = std::make_unique<pugi::xml_document>();
  363. auto ret = xml->load_string(cxml);
  364. +#if !defined(USING_NPUPNP)
  365. ixmlFreeDOMString(cxml);
  366. ixmlDocument_free(descDoc);
  367. +#endif
  368. if (ret.status != pugi::xml_parse_status::status_ok) {
  369. log_debug("Unable to parse xml client description from {}", location);
  370. return false;
  371. diff --git a/src/util/upnp_headers.cc b/src/util/upnp_headers.cc
  372. index c05cffe6..19ba88ca 100644
  373. --- a/src/util/upnp_headers.cc
  374. +++ b/src/util/upnp_headers.cc
  375. @@ -96,18 +96,29 @@ void Headers::writeHeaders(UpnpFileInfo* fileInfo) const
  376. if (headers == nullptr)
  377. return;
  378. +#if defined(USING_NPUPNP)
  379. + for (auto iter : *headers) {
  380. + fileInfo->response_headers.push_back(iter);
  381. + }
  382. +#else
  383. auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
  384. for (auto iter : *headers) {
  385. UpnpExtraHeaders* h = UpnpExtraHeaders_new();
  386. UpnpExtraHeaders_set_resp(h, formatHeader(iter, false).c_str());
  387. UpnpListInsert(head, UpnpListEnd(head), const_cast<UpnpListHead*>(UpnpExtraHeaders_get_node(h)));
  388. }
  389. +#endif
  390. }
  391. std::unique_ptr<std::map<std::string, std::string>> Headers::readHeaders(UpnpFileInfo* fileInfo)
  392. {
  393. auto ret = std::make_unique<std::map<std::string, std::string>>();
  394. +#if defined(USING_NPUPNP)
  395. + for (const auto& entry : fileInfo->request_headers) {
  396. + ret->insert(entry);
  397. + }
  398. +#else
  399. auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
  400. UpnpListIter pos;
  401. for (pos = UpnpListBegin(head); pos != UpnpListEnd(head); pos = UpnpListNext(head, pos)) {
  402. @@ -116,6 +127,7 @@ std::unique_ptr<std::map<std::string, std::string>> Headers::readHeaders(UpnpFil
  403. auto add = parseHeader(header);
  404. ret->insert(add);
  405. }
  406. -
  407. +#endif
  408. +
  409. return ret;
  410. }
  411. diff --git a/src/util/upnp_headers.h b/src/util/upnp_headers.h
  412. index 9677d6e4..dd839236 100644
  413. --- a/src/util/upnp_headers.h
  414. +++ b/src/util/upnp_headers.h
  415. @@ -26,7 +26,9 @@
  416. #ifndef GERBERA_HEADERS_H
  417. #define GERBERA_HEADERS_H
  418. +#if !defined(USING_NPUPNP)
  419. #include <ExtraHeaders.h>
  420. +#endif
  421. #include <map>
  422. #include <memory>
  423. #include <upnp.h>
  424. diff --git a/src/web/web_request_handler.cc b/src/web/web_request_handler.cc
  425. index 71fc9fd5..2ca6601b 100644
  426. --- a/src/web/web_request_handler.cc
  427. +++ b/src/web/web_request_handler.cc
  428. @@ -120,7 +120,11 @@ void WebRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
  429. contentType = mimetype + "; charset=" + DEFAULT_INTERNAL_CHARSET;
  430. +#if defined(USING_NPUPNP)
  431. + UpnpFileInfo_set_ContentType(info, contentType);
  432. +#else
  433. UpnpFileInfo_set_ContentType(info, ixmlCloneDOMString(contentType.c_str()));
  434. +#endif
  435. Headers headers;
  436. headers.addHeader(std::string { "Cache-Control" }, std::string { "no-cache, must-revalidate" });
  437. headers.writeHeaders(info);