UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
upnpapi.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (C) 2011-2012 France Telecom All rights reserved.
6 * Copyright (C) 2021+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
7 * Redistribution only with this Copyright remark. Last modified: 2025-09-13
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * - Neither name of Intel Corporation nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************/
34// Last compare with ./Pupnp source file on 2025-07-16, ver 1.14.21
41#include <upnpapi.hpp>
42
43#include <uuid.hpp>
44#include <miniserver.hpp> // Needed for one of the compile options
45#include <httpreadwrite.hpp>
46#include <ssdp_ctrlpt.hpp>
47#include <ssdp_device.hpp>
48#include <soap_device.hpp>
49#include <soap_ctrlpt.hpp>
50
51#include <UPnPsdk/addrinfo.hpp>
53
54#ifdef _WIN32
55#include <umock/iphlpapi.hpp>
56#else
57#include <umock/ifaddrs.hpp>
58#include <umock/net_if.hpp>
59#endif
60#include <umock/stdio.hpp>
61
62/* Needed for GENA */
63#include <gena.hpp>
64
65#ifdef COMPA_HAVE_WEBSERVER
66#include <urlconfig.hpp>
67#include <webserver.hpp>
68#endif /* COMPA_HAVE_WEBSERVER */
69
70#include <sys/stat.h>
71
72#include <cassert>
73#include <cstdlib>
74#include <cstring>
75
76#ifdef _WIN32
77/* Do not include these files */
78#else
79#include <ifaddrs.h>
80#include <sys/ioctl.h>
81#include <sys/types.h>
82#endif
83
84
85#if !defined(ifr_netmask) || defined(DOXYGEN_RUN) // it's a define if exists
88#define ifr_netmask ifr_addr
89#endif
90
91#if !defined(IN6_IS_ADDR_ULA) || defined(DOXYGEN_RUN)
93#define IN6_IS_ADDR_ULA(a) \
94 ((((__const uint32_t*)(a))[0] & htonl((uint32_t)0xfe000000)) == \
95 htonl((uint32_t)0xfc000000))
96#endif /* IN6_IS_ADDR_ULA */
97
100
103
105pthread_rwlock_t GlobalHndRWLock;
106
109
112
115
118
120WebServerState bWebServerState = WEB_SERVER_DISABLED;
121
124
127
130
133char gIF_NAME[LINE_SIZE] = {'\0'};
135unsigned gIF_INDEX = 0;
136
138char gIF_IPV6[INET6_ADDRSTRLEN] = {'\0'};
143
145char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN] = {'\0'};
150
152char gIF_IPV4[INET_ADDRSTRLEN] = {'\0'};
154char gIF_IPV4_NETMASK[INET_ADDRSTRLEN] = {'\0'};
157
160
167
175
186
190
195
201
207
208#ifdef COMPA_HAVE_OPTION_SSDP
213#endif
214
216typedef union {
218 struct {
219 int handle;
220 int eventId;
221 void* Event;
222 } advertise;
224 struct UpnpNonblockParam action;
225} job_arg;
226
227
228namespace { // anonymous namespace for file scoped old upnpapi items.
229
261 const std::string& a_iface = "") //
262{
263 TRACE("Executing ::UpnpGetIfInfo()")
264
265 // Check if we have to use an index integer number 1 to 99.
266 int idx{0};
267 switch (size(a_iface)) {
268 case 1: {
269 if (std::isdigit(a_iface[0]))
270 idx = std::stoi(a_iface);
271 } break;
272 case 2: {
273 if (std::isdigit(a_iface[0]) && std::isdigit(a_iface[1]))
274 idx = std::stoi(a_iface);
275 } break;
276 } // switch
277
278 UPnPsdk::CNetadapter nadaptObj;
279 try {
280 nadaptObj.get_first(); // May throw exception
281 bool success;
282 if (idx)
283 // No problem with cast. idx is always a small positive number.
284 success = nadaptObj.find_first(static_cast<unsigned int>(idx));
285 else
286 success = nadaptObj.find_first(a_iface);
287 if (!success) {
288 UPnPsdk_LOGERR("MSG1033") "Local network interface with \""
289 << a_iface << "\" not valid for operation or not found.\n";
291 }
292
293 UPnPsdk::SSockaddr saObj;
294 nadaptObj.sockaddr(saObj);
295 if (saObj.is_loopback()) {
296 UPnPsdk_LOGERR("MSG1045") "Local network interface address \""
297 << a_iface << "\" is not supported.\n";
299 }
300
301 // Get gIF_NAME and gIF_INDEX
302 ::memset(gIF_NAME, 0, sizeof(gIF_NAME));
303 ::strncpy(gIF_NAME, nadaptObj.name().c_str(), sizeof(gIF_NAME) - 1);
304 gIF_INDEX = nadaptObj.index();
305
306 // With default lookup, restrict finding to the current selected
307 // adapter.
308 if (a_iface.empty())
309 nadaptObj.find_first(gIF_INDEX);
310
311 ::memset(gIF_IPV6, 0, sizeof(gIF_IPV6));
312 ::memset(gIF_IPV6_ULA_GUA, 0, sizeof(gIF_IPV6_ULA_GUA));
313 ::memset(gIF_IPV4, 0, sizeof(gIF_IPV4));
314 ::memset(gIF_IPV4_NETMASK, 0, sizeof(gIF_IPV4_NETMASK));
315
316 // Scan all provided local interface addresses to find the wanted one.
317 do {
318 nadaptObj.sockaddr(saObj);
319 if (saObj.ss.ss_family == AF_INET6) {
320 if (gIF_IPV6[0] == '\0' &&
321 (IN6_IS_ADDR_LINKLOCAL(&saObj.sin6.sin6_addr))) {
322 // Strip leading bracket on copying.
323 ::strncpy(gIF_IPV6, saObj.netaddr().c_str() + 1,
324 sizeof(gIF_IPV6) - 1);
325 // Strip trailing scope id if any.
326 if (char* chptr{::strchr(gIF_IPV6, '%')})
327 *chptr = '\0';
328 // Strip trailing bracket if any.
329 else if (char* chptr{::strchr(gIF_IPV6, ']')})
330 *chptr = '\0';
331 gIF_IPV6_PREFIX_LENGTH = nadaptObj.bitmask();
332 } else if (gIF_IPV6_ULA_GUA[0] == '\0') {
333 // Strip leading bracket on copying.
334 ::strncpy(gIF_IPV6_ULA_GUA, saObj.netaddr().c_str() + 1,
335 sizeof(gIF_IPV6_ULA_GUA) - 1);
336 // Strip trailing scope id if any.
337 if (char* chptr{::strchr(gIF_IPV6, '%')})
338 *chptr = '\0';
339 // Strip trailing bracket if any.
340 else if (char* chptr{::strchr(gIF_IPV6_ULA_GUA, ']')})
341 *chptr = '\0';
343 }
344
345 } else {
346
347 UPnPsdk_LOGCRIT("MSG1029") "Unsupported address family("
348 << saObj.ss.ss_family << "), only AF_INET6(" << AF_INET6
349 << ") is valid.\n";
351 }
352
353 } while (nadaptObj.find_next() && gIF_IPV6[0] == '\0' &&
354 gIF_IPV6_ULA_GUA[0] == '\0');
355 } catch (const std::exception& ex) {
356 UPnPsdk_LOGCATCH("MSG1006") "catched next line...\n" << ex.what();
358 }
359
360 return UPNP_E_SUCCESS;
361}
362
363
366
367#if defined(COMPA_HAVE_DEVICE_DESCRIPTION) || \
368 defined(COMPA_HAVE_CTRLPT_DESCRIPTION) || defined(DOXYGEN_RUN)
377 // Handle 0 is not used as NULL translates to 0 when passed as a handle
378 int i = 1;
379
380 while (i < NUM_HANDLE && HandleTable[i] != nullptr)
381 ++i;
382 if (i == NUM_HANDLE)
383 return UPNP_E_OUTOF_HANDLE;
384 else
385 return i;
386}
387#endif // defined(COMPA_HAVE_DEVICE_DESCRIPTION) ||
388 // defined(COMPA_HAVE_CTRLPT_DESCRIPTION)
389
390#if defined(COMPA_HAVE_DEVICE_DESCRIPTION) || \
391 defined(COMPA_HAVE_CTRLPT_DESCRIPTION) || defined(DOXYGEN_RUN)
399 int Upnp_Handle) {
400 int ret = UPNP_E_INVALID_HANDLE;
401
402 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
403 "FreeHandle: entering, Handle is %d\n", Upnp_Handle);
404 if (Upnp_Handle < 1 || Upnp_Handle >= NUM_HANDLE) {
405 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
406 "FreeHandle: Handle %d is out of range\n", Upnp_Handle);
407 } else if (HandleTable[Upnp_Handle] == nullptr) {
408 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
409 "FreeHandle: HandleTable[%d] is nullptr\n", Upnp_Handle);
410 } else {
411 free(HandleTable[Upnp_Handle]);
412 HandleTable[Upnp_Handle] = nullptr;
413 ret = UPNP_E_SUCCESS;
414 }
415 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
416 "FreeHandle: exiting, ret = %d.\n", ret);
417
418 return ret;
419}
420
421#endif // defined(COMPA_HAVE_DEVICE_DESCRIPTION) ||
422 // defined(COMPA_HAVE_CTRLPT_DESCRIPTION)
423
424} // anonymous namespace
425
426
427namespace compa {
428namespace {
429
431pthread_mutex_t sdkInit_mutex = PTHREAD_MUTEX_INITIALIZER;
432
434#if defined(COMPA_HAVE_DEVICE_DESCRIPTION)
435int UpnpRegisterRootDevice3(const char* const DescUrl, const Upnp_FunPtr Fun,
436 const void* const Cookie,
437 UpnpDevice_Handle* const Hnd,
438 const int AddressFamily,
439 const char* const LowerDescUrl) {
440 TRACE("Executing UpnpRegisterRootDevice3() (same as "
441 "UpnpRegisterRootDevice4())")
442 Handle_Info* HInfo;
443 int retVal = 0;
444#ifdef COMPA_HAVE_DEVICE_GENA
445 int hasServiceTable{0};
446#endif
447 HandleLock();
448
449 // Do some basic parameter checks.
450 if (UpnpSdkInit != 1) {
451 retVal = UPNP_E_FINISH;
452 goto exit_function;
453 }
454 if (Hnd == nullptr || Fun == nullptr || DescUrl == nullptr ||
455 strlen(DescUrl) == 0 ||
456 (AddressFamily != AF_INET && AddressFamily != AF_INET6)) {
457 retVal = UPNP_E_INVALID_PARAM;
458 goto exit_function;
459 }
460
461 // Get a UPnP Unit handle and initialize handle info for a UPnP Device.
462 *Hnd = GetFreeHandle();
463 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
464 retVal = UPNP_E_OUTOF_MEMORY;
465 goto exit_function;
466 }
467 HInfo = (Handle_Info*)malloc(sizeof(Handle_Info));
468 if (HInfo == nullptr) {
469 retVal = UPNP_E_OUTOF_MEMORY;
470 goto exit_function;
471 }
472 memset(HInfo, 0, sizeof(Handle_Info));
473 HandleTable[*Hnd] = HInfo;
474
475 HInfo->HType = HND_DEVICE; // Set handle info to UPnP Device.
476
477 strncpy(HInfo->DescURL, DescUrl, sizeof(HInfo->DescURL) - 1);
478 if (LowerDescUrl == nullptr)
479 strncpy(HInfo->LowerDescURL, DescUrl, sizeof(HInfo->LowerDescURL) - 1);
480 else
481 strncpy(HInfo->LowerDescURL, LowerDescUrl,
482 sizeof(HInfo->LowerDescURL) - 1);
483 UPnPsdk_LOGINFO(
484 "MSG1050") "Following Root UDevice local URL will be used when "
485 "responding to requests from control points: "
486 << HInfo->LowerDescURL << ".\n";
487 HInfo->Callback = Fun;
488 HInfo->Cookie = (char*)Cookie;
489 HInfo->MaxAge = DEFAULT_MAXAGE;
490 HInfo->DeviceList = nullptr;
491 HInfo->ServiceList = nullptr;
492 HInfo->DescDocument = nullptr;
493#ifdef COMPA_HAVE_CTRLPT_SSDP
494 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
495 HInfo->ClientSubList = nullptr;
496#endif
499 HInfo->DeviceAf = AddressFamily;
500
501 // Get own device description from local XML file.
502 retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
503 if (retVal != UPNP_E_SUCCESS) {
504#ifdef COMPA_HAVE_CTRLPT_SSDP
505 ListDestroy(&HInfo->SsdpSearchList, 0);
506#endif
507 FreeHandle(*Hnd);
508 goto exit_function;
509 }
510 UPnPsdk_LOGINFO(
511 "MSG1051") "UpnpRegisterRootDevice3(or 4): Valid Description\n"
512 "UpnpRegisterRootDevice3(or 4): DescURL = "
513 << HInfo->DescURL << ".\n";
514
515 HInfo->DeviceList =
517 if (!HInfo->DeviceList) {
518#ifdef COMPA_HAVE_CTRLPT_SSDP
519 ListDestroy(&HInfo->SsdpSearchList, 0);
520#endif
522 FreeHandle(*Hnd);
523 UPnPsdk_LOGCRIT("MSG1052") "UpnpRegisterRootDevice3(or 4): No devices "
524 "found for RootDevice.\n";
525 retVal = UPNP_E_INVALID_DESC;
526 goto exit_function;
527 }
528
529 HInfo->ServiceList =
530 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
531 if (!HInfo->ServiceList) {
532 UPnPsdk_LOGCRIT(
533 "MSG1054") "UpnpRegisterRootDevice3(or 4): No services found for "
534 "RootDevice.\n";
535 }
536
537#ifdef COMPA_HAVE_DEVICE_GENA
538 /*
539 * GENA SET UP
540 */
541 UPnPsdk_LOGINFO("MSG1055") "UpnpRegisterRootDevice3(or 4): Gena Check.\n";
542 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
543 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
544 &HInfo->ServiceTable, HInfo->DescURL);
545 if (hasServiceTable) {
546 UPnPsdk_LOGINFO(
547 "MSG1056") "UpnpRegisterRootDevice3(or 4): GENA Service Table\n"
548 "Here are the known services:\n";
549 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
550 } else {
551 UPnPsdk_LOGINFO(
552 "MSG1062") "\nUpnpRegisterRootDevice3(or 4): Empty service table\n";
553 }
554#endif // COMPA_HAVE_CTRLPT_GENA || COMPA_HAVE_DEVICE_GENA
555
556 switch (AddressFamily) {
557 case AF_INET:
559 break;
560 default:
562 }
563
564 retVal = UPNP_E_SUCCESS;
565
566exit_function:
567 UPnPsdk_LOGINFO(
568 "MSG1064") "Exiting UpnpRegisterRootDevice3(or 4), return value == "
569 << retVal << ".\n";
570 HandleUnlock();
571
572 return retVal;
573}
574#endif // COMPA_HAVE_DEVICE_DESCRIPTION
575
576} // anonymous namespace
577} // namespace compa
578
579
580#ifdef COMPA_HAVE_DEVICE_SSDP // Needed to compile with warings as errors --Ingo
584static void free_advertise_arg(job_arg* arg) {
585 if (arg->advertise.Event) {
586 free(arg->advertise.Event);
587 }
588 free(arg);
589}
590#endif
591
592#ifdef COMPA_HAVE_CTRLPT_SOAP
596static void free_action_arg(job_arg* arg) {
597 if (arg->action.Header) {
599 }
600 if (arg->action.Act) {
602 }
603 free(arg);
604}
605#endif
606
607
614static int UpnpInitMutexes() {
615#ifdef __CYGWIN__
616 /* On Cygwin, pthread_mutex_init() fails without this memset. */
617 /* TODO: Fix Cygwin so we don't need this memset(). */
618 memset(&GlobalHndRWLock, 0, sizeof(GlobalHndRWLock));
619#endif
620 if (pthread_rwlock_init(&GlobalHndRWLock, NULL) != 0) {
621 return UPNP_E_INIT_FAILED;
622 }
623#ifdef COMPA_HAVE_OPTION_SSDP
624 // Mutex to synchronize the uuid creation process.
626#endif
627 /* initialize subscribe mutex. */
628#ifdef COMPA_HAVE_CTRLPT_GENA
629 if (clientSubscribeMutexInit() != 0) {
630 return UPNP_E_INIT_FAILED;
631 }
632#endif
633 return UPNP_E_SUCCESS;
634}
635
643 int ret = UPNP_E_SUCCESS;
644 ThreadPoolAttr attr;
645
646 TPAttrInit(&attr);
653
655 ret = UPNP_E_INIT_FAILED;
656 goto exit_function;
657 }
658
660 ret = UPNP_E_INIT_FAILED;
661 goto exit_function;
662 }
663
665 ret = UPNP_E_INIT_FAILED;
666 goto exit_function;
667 }
668
669exit_function:
670 if (ret != UPNP_E_SUCCESS) {
671 UpnpSdkInit = 0;
672 UpnpFinish();
673 }
674
675 return ret;
676}
677
689static int UpnpInitPreamble() {
690 TRACE("Executing UpnpInitPreamble()")
691 int retVal = UPNP_E_SUCCESS;
692
693 /* needed by SSDP or other parts. */
694 srand((unsigned int)time(NULL));
695
696 /* Initialize debug output. */
697 retVal = UpnpInitLog();
698 if (retVal != UPNP_E_SUCCESS) {
699 /* UpnpInitLog does not return a valid UPNP_E_*. */
700 return UPNP_E_INIT_FAILED;
701 }
702
703 /* Initialize SDK global mutexes. */
704 retVal = UpnpInitMutexes();
705 if (retVal != UPNP_E_SUCCESS) {
706 return retVal;
707 }
708
709#ifdef COMPA_HAVE_OPTION_SSDP
710 /* Create the NLS uuid. */
711 uuid_upnp nls_uuid;
712 uuid_create(&nls_uuid);
714#endif
715
716 /* Initializes the handle list. */
717 HandleLock();
718 for (int i{0}; i < NUM_HANDLE; ++i) {
719 HandleTable[i] = nullptr;
720 }
721 HandleUnlock();
722
723 /* Initialize SDK global thread pools. */
724 retVal = UpnpInitThreadPools();
725 if (retVal != UPNP_E_SUCCESS) {
726 return retVal;
727 }
728
729#ifdef COMPA_HAVE_DEVICE_SOAP
731#endif
732
733#ifdef COMPA_HAVE_DEVICE_GENA
735#endif
736
737 /* Initialize the SDK timer thread. */
739 if (retVal != UPNP_E_SUCCESS) {
740 UpnpFinish();
741
742 return retVal;
743 }
744
745 return UPNP_E_SUCCESS;
746}
747
758 [[maybe_unused]] in_port_t DestPort) {
759 UPnPsdk_LOGINFO("MSG1061") "Executing...\n";
760 int retVal;
761
762#ifdef COMPA_HAVE_MINISERVER
763 LOCAL_PORT_V4 = DestPort;
764 LOCAL_PORT_V6 = DestPort;
765 LOCAL_PORT_V6_ULA_GUA = DestPort;
766 retVal =
768 if (retVal != UPNP_E_SUCCESS) {
769 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
770 "Miniserver failed to start\n");
771 UpnpFinish();
772 return retVal;
773 }
774#endif
775
776 retVal = UpnpEnableWebserver(WEB_SERVER_ENABLED);
777 if (retVal != UPNP_E_SUCCESS) {
778 UpnpFinish();
779 return retVal;
780 }
781
782 UPnPsdk_LOGINFO("MSG1066") "Finished.\n";
783 return UPNP_E_SUCCESS;
784}
785
786int UpnpInit2(const char* IfName, unsigned short DestPort) {
787 UPnPsdk_LOGINFO("MSG1096") "Executing...\n";
788 int retVal;
789
790 // The mutex must be initialized.
791 if (pthread_mutex_lock(&compa::sdkInit_mutex) != 0) {
792 retVal = UPNP_E_INIT_FAILED;
793 goto exit_function;
794 }
795
796 /* Check if we're already initialized. */
797 if (UpnpSdkInit == 1) {
798 retVal = UPNP_E_INIT;
799 goto exit_function;
800 }
801
802 /* Set the UpnpSdkInit flag to 1 to indicate we're successfully
803 * initialized. */
804 UpnpSdkInit = 1;
805
806 /* Perform initialization preamble. */
807 retVal = UpnpInitPreamble();
808 if (retVal != UPNP_E_SUCCESS) {
809 goto exit_function;
810 }
811
812 /* Retrieve interface information (Addresses, index, etc). */
813 retVal = ::UpnpGetIfInfo(IfName == nullptr ? "" : IfName);
814 if (retVal != UPNP_E_SUCCESS) {
815 goto exit_function;
816 }
817
818 /* Finish initializing the SDK. */
819 retVal = UpnpInitStartServers(DestPort);
820 if (retVal != UPNP_E_SUCCESS) {
821 goto exit_function;
822 }
823
824exit_function:
825 if (retVal != UPNP_E_SUCCESS && retVal != UPNP_E_INIT) {
826 UpnpFinish();
827 }
828 pthread_mutex_unlock(&compa::sdkInit_mutex);
829 return retVal;
830}
831
832#ifdef DEBUG
839 ThreadPool* tp,
840 const char* DbgFileName,
842 int DbgLineNo,
844 const char* msg) {
845 ThreadPoolStats stats;
846 ThreadPoolGetStats(tp, &stats);
847 UpnpPrintf(UPNP_INFO, API, DbgFileName, DbgLineNo,
848 "%s\n"
849 "High Jobs pending: %d\n"
850 "Med Jobs Pending: %d\n"
851 "Low Jobs Pending: %d\n"
852 "Average wait in High Q in milliseconds: %lf\n"
853 "Average wait in Med Q in milliseconds: %lf\n"
854 "Average wait in Low Q in milliseconds: %lf\n"
855 "Max Threads Used: %d\n"
856 "Worker Threads: %d\n"
857 "Persistent Threads: %d\n"
858 "Idle Threads: %d\n"
859 "Total Threads: %d\n"
860 "Total Work Time: %lf\n"
861 "Total Idle Time: %lf\n",
862 msg, stats.currentJobsHQ, stats.currentJobsMQ,
863 stats.currentJobsLQ, stats.avgWaitHQ, stats.avgWaitMQ,
864 stats.avgWaitLQ, stats.maxThreads, stats.workerThreads,
865 stats.persistentThreads, stats.idleThreads, stats.totalThreads,
866 stats.totalWorkTime, stats.totalIdleTime);
867}
868#else
871#define PrintThreadPoolStats(tp, DbgFileName, DbgLineNo, msg) \
872 do { \
873 } while (0)
874#endif /* DEBUG */
875
877 TRACE("Executing UpnpFinish()")
878 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
879 "Inside UpnpFinish: UpnpSdkInit is %d\n", UpnpSdkInit);
880#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
881 UpnpDevice_Handle device_handle;
882#endif
883#ifdef COMPA_HAVE_CTRLPT_DESCRIPTION
884 UpnpClient_Handle client_handle;
885#endif
886 [[maybe_unused]] struct Handle_Info* temp{nullptr};
887#ifdef UPnPsdk_HAVE_OPENSSL
888 freeSslCtx();
889#endif
890 if (UpnpSdkInit != 1)
891 return UPNP_E_FINISH;
892 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
893 "UpnpFinish: UpnpSdkInit is ONE\n");
894 // May be usable for DEBUG:
895 // PrintThreadPoolStats(&gSendThreadPool, __FILE__, __LINE__,
896 // "Send Thread Pool");
897 // PrintThreadPoolStats(&gRecvThreadPool, __FILE__, __LINE__,
898 // "Recv Thread Pool");
899 // PrintThreadPoolStats(&gMiniServerThreadPool, __FILE__, __LINE__,
900 // "MiniServer Thread Pool");
901#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
902 while (GetDeviceHandleInfo(0, AF_INET, &device_handle, &temp) ==
903 HND_DEVICE) {
904 UpnpUnRegisterRootDevice(device_handle);
905 }
906 while (GetDeviceHandleInfo(0, AF_INET6, &device_handle, &temp) ==
907 HND_DEVICE) {
908 UpnpUnRegisterRootDevice(device_handle);
909 }
910#endif
911#ifdef COMPA_HAVE_CTRLPT_DESCRIPTION
912 while (HND_CLIENT == GetClientHandleInfo(&client_handle, &temp)) {
913 UpnpUnRegisterClient(client_handle);
914 }
915#endif
917#ifdef COMPA_HAVE_MINISERVER
919#endif
920#ifdef COMPA_HAVE_WEBSERVER
922#endif
924 PrintThreadPoolStats(&gMiniServerThreadPool, __FILE__, __LINE__,
925 "MiniServer Thread Pool");
927 PrintThreadPoolStats(&gSendThreadPool, __FILE__, __LINE__,
928 "Send Thread Pool");
930 PrintThreadPoolStats(&gRecvThreadPool, __FILE__, __LINE__,
931 "Recv Thread Pool");
932#ifdef COMPA_HAVE_CTRLPT_GENA
934#endif
935 pthread_rwlock_destroy(&GlobalHndRWLock);
936#ifdef COMPA_HAVE_OPTION_SSDP
937 uuidMutexDestroy(); // May fail but not checked due to compatibility.
938#endif
939 UpnpRemoveAllVirtualDirs(); /* remove all virtual dirs */
940 UpnpSdkInit = 0;
941 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
942 "Exiting UpnpFinish: UpnpSdkInit is :%d:\n", UpnpSdkInit);
943 UpnpCloseLog();
944
945 return UPNP_E_SUCCESS;
946}
947
948unsigned short UpnpGetServerPort() {
949 if (UpnpSdkInit != 1)
950 return 0u;
951
952 return LOCAL_PORT_V4;
953}
954
955unsigned short UpnpGetServerPort6() {
956#ifdef UPNP_ENABLE_IPV6
957 if (UpnpSdkInit != 1)
958 return 0u;
959
960 return LOCAL_PORT_V6;
961#else
962 return 0u;
963#endif
964}
965
966unsigned short UpnpGetServerUlaGuaPort6() {
967#ifdef UPNP_ENABLE_IPV6
968 if (UpnpSdkInit != 1)
969 return 0u;
970
972#else
973 return 0u;
974#endif
975}
976
978 if (UpnpSdkInit != 1)
979 return NULL;
980
981 return gIF_IPV4;
982}
983
985#ifdef UPNP_ENABLE_IPV6
986 if (UpnpSdkInit != 1)
987 return NULL;
988
989 return gIF_IPV6;
990#else
991 return NULL;
992#endif
993}
994
996#ifdef UPNP_ENABLE_IPV6
997 if (UpnpSdkInit != 1)
998 return NULL;
999
1000 return gIF_IPV6_ULA_GUA;
1001#else
1002 return NULL;
1003#endif
1004}
1005
1006#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1007int UpnpRegisterRootDevice(const char* const DescUrl, const Upnp_FunPtr Fun,
1008 const void* const Cookie,
1009 UpnpDevice_Handle* const Hnd) {
1010 struct Handle_Info* HInfo = NULL;
1011 int retVal = 0;
1012#ifdef COMPA_HAVE_DEVICE_GENA
1013 int hasServiceTable{0};
1014#endif
1015 HandleLock();
1016
1017 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1018 "Inside UpnpRegisterRootDevice\n");
1019
1020 if (UpnpSdkInit != 1) {
1021 retVal = UPNP_E_FINISH;
1022 goto exit_function;
1023 }
1024
1025 if (Hnd == NULL || Fun == NULL || DescUrl == NULL ||
1026 strlen(DescUrl) == (size_t)0) {
1027 retVal = UPNP_E_INVALID_PARAM;
1028 goto exit_function;
1029 }
1030
1031 *Hnd = GetFreeHandle();
1032 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
1033 retVal = UPNP_E_OUTOF_MEMORY;
1034 goto exit_function;
1035 }
1036
1037 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
1038 if (HInfo == NULL) {
1039 retVal = UPNP_E_OUTOF_MEMORY;
1040 goto exit_function;
1041 }
1042 memset(HInfo, 0, sizeof(struct Handle_Info));
1043 HandleTable[*Hnd] = HInfo;
1044
1045 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Root device URL is %s\n",
1046 DescUrl);
1047
1048 HInfo->aliasInstalled = 0;
1049 HInfo->HType = HND_DEVICE;
1050 strncpy(HInfo->DescURL, DescUrl, sizeof(HInfo->DescURL) - 1);
1051 strncpy(HInfo->LowerDescURL, DescUrl, sizeof(HInfo->LowerDescURL) - 1);
1052 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1053 "Following Root Device URL will be used when answering to "
1054 "legacy CPs %s\n",
1055 HInfo->LowerDescURL);
1056 HInfo->Callback = Fun;
1057 HInfo->Cookie = (char*)Cookie;
1058 HInfo->MaxAge = DEFAULT_MAXAGE;
1059 HInfo->DeviceList = NULL;
1060 HInfo->ServiceList = NULL;
1061 HInfo->DescDocument = NULL;
1062#ifdef COMPA_HAVE_CTRLPT_SSDP
1063 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1064 HInfo->ClientSubList = NULL;
1065#endif
1068 HInfo->DeviceAf = AF_INET;
1069
1070 retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
1071 if (retVal != UPNP_E_SUCCESS) {
1072 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1073 "UpnpRegisterRootDevice: error downloading Document: "
1074 "%d\n",
1075 retVal);
1076#ifdef COMPA_HAVE_CTRLPT_SSDP
1077 ListDestroy(&HInfo->SsdpSearchList, 0);
1078#endif
1079 FreeHandle(*Hnd);
1080 goto exit_function;
1081 }
1082 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1083 "UpnpRegisterRootDevice: Valid Description\n"
1084 "UpnpRegisterRootDevice: DescURL : %s\n",
1085 HInfo->DescURL);
1086
1087 HInfo->DeviceList =
1089 if (!HInfo->DeviceList) {
1090#ifdef COMPA_HAVE_CTRLPT_SSDP
1091 ListDestroy(&HInfo->SsdpSearchList, 0);
1092#endif
1094 FreeHandle(*Hnd);
1095 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
1096 "UpnpRegisterRootDevice: No devices found for "
1097 "RootDevice\n");
1098 retVal = UPNP_E_INVALID_DESC;
1099 goto exit_function;
1100 }
1101
1102 HInfo->ServiceList =
1103 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
1104 if (!HInfo->ServiceList) {
1105 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
1106 "UpnpRegisterRootDevice: No services found for "
1107 "RootDevice\n");
1108 }
1109
1110#ifdef COMPA_HAVE_DEVICE_GENA
1111 /*
1112 * GENA SET UP
1113 */
1114 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1115 "UpnpRegisterRootDevice: Gena Check\n");
1116 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
1117 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
1118 &HInfo->ServiceTable, HInfo->DescURL);
1119 if (hasServiceTable) {
1120 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1121 "UpnpRegisterRootDevice: GENA Service Table\n"
1122 "Here are the known services:\n");
1123 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
1124 } else {
1125 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1126 "\nUpnpRegisterRootDevice: Empty service table\n");
1127 }
1128#endif // COMPA_HAVE_DEVICE_GENA
1129
1131
1132 retVal = UPNP_E_SUCCESS;
1133
1134exit_function:
1135 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1136 "Exiting RegisterRootDevice, return value == %d\n", retVal);
1137 HandleUnlock();
1138
1139 return retVal;
1140}
1141#endif /* COMPA_HAVE_DEVICE_DESCRIPTION */
1142
1143#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1147static int GetDescDocumentAndURL(
1148 /* [in] pointer to server address structure. */
1149 Upnp_DescType descriptionType,
1150 /* [in] . */
1151 char* description,
1152 /* [in] . */
1153 int config_baseURL,
1154 /* [in] . */
1155 int AddressFamily,
1156 /* [out] . */
1157 IXML_Document** xmlDoc,
1158 /* [out] . */
1159 char descURL[LINE_SIZE]);
1160#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1161
1162#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1163int UpnpRegisterRootDevice2(const Upnp_DescType descriptionType,
1164 const char* const description_const,
1165 const size_t bufferLen, /* ignored */
1166 const int config_baseURL, const Upnp_FunPtr Fun,
1167 const void* const Cookie,
1168 UpnpDevice_Handle* const Hnd) {
1169 struct Handle_Info* HInfo = NULL;
1170 int retVal = 0;
1171 char* description = (char*)description_const;
1172 (void)bufferLen;
1173#ifdef COMPA_HAVE_DEVICE_GENA
1174 int hasServiceTable{0};
1175#endif
1176 HandleLock();
1177
1178 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1179 "Inside UpnpRegisterRootDevice2\n");
1180
1181 if (UpnpSdkInit != 1) {
1182 retVal = UPNP_E_FINISH;
1183 goto exit_function;
1184 }
1185
1186 if (Hnd == NULL || Fun == NULL) {
1187 retVal = UPNP_E_INVALID_PARAM;
1188 goto exit_function;
1189 }
1190
1191 *Hnd = GetFreeHandle();
1192 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
1193 retVal = UPNP_E_OUTOF_MEMORY;
1194 goto exit_function;
1195 }
1196
1197 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
1198 if (HInfo == NULL) {
1199 retVal = UPNP_E_OUTOF_MEMORY;
1200 goto exit_function;
1201 }
1202 memset(HInfo, 0, sizeof(struct Handle_Info));
1203 HandleTable[*Hnd] = HInfo;
1204
1205 /* prevent accidental removal of a non-existent alias */
1206 HInfo->aliasInstalled = 0;
1207
1208 retVal =
1209 GetDescDocumentAndURL(descriptionType, description, config_baseURL,
1210 AF_INET, &HInfo->DescDocument, HInfo->DescURL);
1211 if (retVal != UPNP_E_SUCCESS) {
1212 FreeHandle(*Hnd);
1213 goto exit_function;
1214 }
1215
1216#ifdef UPNPLIB_PUPNP_BUG
1217 // Error if compiling old code with build type Release: output may be
1218 // truncated copying 179 bytes from a string of length 179
1219 // [-Werror=stringop-truncation]. We have to fix it here otherwise it won't
1220 // compile. --Ingo
1221 strncpy(HInfo->LowerDescURL, HInfo->DescURL,
1222 sizeof(HInfo->LowerDescURL) - 1);
1223#else
1224 strncpy(HInfo->LowerDescURL, HInfo->DescURL, sizeof(HInfo->LowerDescURL));
1225#endif
1226 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1227 "Following Root Device URL will be used when answering to "
1228 "legacy CPs %s\n",
1229 HInfo->LowerDescURL);
1230 HInfo->aliasInstalled = config_baseURL != 0;
1231 HInfo->HType = HND_DEVICE;
1232 HInfo->Callback = Fun;
1233 HInfo->Cookie = (char*)Cookie;
1234 HInfo->MaxAge = DEFAULT_MAXAGE;
1235 HInfo->DeviceList = NULL;
1236 HInfo->ServiceList = NULL;
1237#ifdef COMPA_HAVE_CTRLPT_SSDP
1238 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1239 HInfo->ClientSubList = NULL;
1240#endif
1243 HInfo->DeviceAf = AF_INET;
1244
1245 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1246 "UpnpRegisterRootDevice2: Valid Description\n"
1247 "UpnpRegisterRootDevice2: DescURL : %s\n",
1248 HInfo->DescURL);
1249
1250 HInfo->DeviceList =
1252 if (!HInfo->DeviceList) {
1253#ifdef COMPA_HAVE_CTRLPT_SSDP
1254 ListDestroy(&HInfo->SsdpSearchList, 0);
1255#endif
1257 FreeHandle(*Hnd);
1258 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1259 "UpnpRegisterRootDevice2: No devices found for "
1260 "RootDevice\n");
1261 retVal = UPNP_E_INVALID_DESC;
1262 goto exit_function;
1263 }
1264
1265 HInfo->ServiceList =
1266 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
1267 if (!HInfo->ServiceList) {
1268 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1269 "UpnpRegisterRootDevice2: No services found for "
1270 "RootDevice\n");
1271 }
1272
1273#ifdef COMPA_HAVE_DEVICE_GENA
1274 /*
1275 * GENA SET UP
1276 */
1277 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1278 "UpnpRegisterRootDevice2: Gena Check\n");
1279 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
1280 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
1281 &HInfo->ServiceTable, HInfo->DescURL);
1282 if (hasServiceTable) {
1283 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1284 "UpnpRegisterRootDevice2: GENA Service Table\n"
1285 "Here are the known services: \n");
1286 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
1287 } else {
1288 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1289 "\nUpnpRegisterRootDevice2: Empty service table\n");
1290 }
1291#endif // COMPA_HAVE_DEVICE_GENA
1292
1294
1295 retVal = UPNP_E_SUCCESS;
1296
1297exit_function:
1298 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1299 "Exiting RegisterRootDevice2, return value == %d\n", retVal);
1300 HandleUnlock();
1301
1302 return retVal;
1303}
1304#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1305
1306#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1307// UpnpRegisterRootDevice3() (without LowerDescUrl argument).
1308int UpnpRegisterRootDevice3(const char* const DescUrl, const Upnp_FunPtr Fun,
1309 const void* const Cookie,
1310 UpnpDevice_Handle* const Hnd,
1311 const int AddressFamily) {
1312 return compa::UpnpRegisterRootDevice3(DescUrl, Fun, Cookie, Hnd,
1313 AddressFamily, nullptr);
1314}
1315
1316// Same as UpnpRegisterRootDevice3() but with LowerDescUrl argument.
1317int UpnpRegisterRootDevice4(const char* const DescUrl, const Upnp_FunPtr Fun,
1318 const void* const Cookie,
1319 UpnpDevice_Handle* const Hnd,
1320 const int AddressFamily,
1321 const char* const LowerDescUrl) {
1322 return compa::UpnpRegisterRootDevice3(DescUrl, Fun, Cookie, Hnd,
1323 AddressFamily, LowerDescUrl);
1324}
1325#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1326
1327#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1329 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1330 "Inside UpnpUnRegisterRootDevice\n");
1331 return UpnpUnRegisterRootDeviceLowPower(Hnd, -1, -1, -1);
1332}
1333
1335 int SleepPeriod, int RegistrationState) {
1336 int retVal = 0;
1337 struct Handle_Info* HInfo = NULL;
1338
1339 if (UpnpSdkInit != 1)
1340 return UPNP_E_FINISH;
1341 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1342 "Inside UpnpUnRegisterRootDeviceLowPower\n");
1343#ifdef COMPA_HAVE_DEVICE_GENA
1345 return UPNP_E_INVALID_HANDLE;
1346#endif
1347
1348 HandleLock();
1349 switch (GetHandleInfo(Hnd, &HInfo)) {
1350 case HND_INVALID:
1351 HandleUnlock();
1352 return UPNP_E_INVALID_HANDLE;
1353 default:
1354 break;
1355 }
1356 HInfo->PowerState = PowerState;
1357 if (SleepPeriod < 0)
1358 SleepPeriod = -1;
1359 HInfo->SleepPeriod = SleepPeriod;
1361 HandleUnlock();
1362
1363 retVal = AdvertiseAndReply(-1, Hnd, (enum SsdpSearchType)0,
1364 (struct sockaddr*)NULL, (char*)NULL, (char*)NULL,
1365 (char*)NULL, HInfo->MaxAge);
1366
1367 HandleLock();
1368 switch (GetHandleInfo(Hnd, &HInfo)) {
1369 case HND_INVALID:
1370 HandleUnlock();
1371 return UPNP_E_INVALID_HANDLE;
1372 default:
1373 break;
1374 }
1378#ifdef COMPA_HAVE_CTRLPT_SSDP
1379 ListDestroy(&HInfo->SsdpSearchList, 0);
1380#endif
1381#ifdef COMPA_HAVE_WEBSERVER
1382 if (HInfo->aliasInstalled)
1383 web_server_set_alias(NULL, NULL, 0, 0);
1384#endif
1385 switch (HInfo->DeviceAf) {
1386 case AF_INET:
1388 break;
1389 case AF_INET6:
1391 break;
1392 default:
1393 break;
1394 }
1395 FreeHandle(Hnd);
1396 HandleUnlock();
1397
1398 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1399 "Exiting UpnpUnRegisterRootDeviceLowPower\n");
1400
1401 return retVal;
1402}
1403#endif /* COMPA_HAVE_DEVICE_DESCRIPTION */
1404
1405#ifdef COMPA_HAVE_CTRLPT_DESCRIPTION
1406int UpnpRegisterClient(Upnp_FunPtr Fun, const void* Cookie,
1407 UpnpClient_Handle* Hnd) {
1408 struct Handle_Info* HInfo;
1409
1410 if (UpnpSdkInit != 1)
1411 return UPNP_E_FINISH;
1412 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1413 "Inside UpnpRegisterClient \n");
1414 if (Fun == NULL || Hnd == NULL)
1415 return UPNP_E_INVALID_PARAM;
1416
1417 HandleLock();
1418 if ((NUM_HANDLE - 1) <=
1421 HandleUnlock();
1423 }
1424 if ((*Hnd = GetFreeHandle()) == UPNP_E_OUTOF_HANDLE) {
1425 HandleUnlock();
1426 return UPNP_E_OUTOF_MEMORY;
1427 }
1428 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
1429 if (HInfo == NULL) {
1430 HandleUnlock();
1431 return UPNP_E_OUTOF_MEMORY;
1432 }
1433 HInfo->HType = HND_CLIENT;
1434 HInfo->Callback = Fun;
1435 HInfo->Cookie = (char*)Cookie;
1436 HInfo->ClientSubList = NULL;
1437 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1438#ifdef COMPA_HAVE_DEVICE_SSDP
1439 HInfo->MaxAge = 0;
1442#endif
1443 HandleTable[*Hnd] = HInfo;
1445 HandleUnlock();
1446
1447 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1448 "Exiting UpnpRegisterClient \n");
1449
1450 return UPNP_E_SUCCESS;
1451}
1452
1454 struct Handle_Info* HInfo;
1455 ListNode* node = NULL;
1456 SsdpSearchArg* searchArg = NULL;
1457
1458 if (UpnpSdkInit != 1)
1459 return UPNP_E_FINISH;
1460 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1461 "Inside UpnpUnRegisterClient \n");
1462
1463 HandleLock();
1465 HandleUnlock();
1466 return UPNP_E_INVALID_HANDLE;
1467 }
1468 HandleUnlock();
1469
1470#ifdef COMPA_HAVE_CTRLPT_GENA
1472 return UPNP_E_INVALID_HANDLE;
1473#endif
1474 HandleLock();
1475 switch (GetHandleInfo(Hnd, &HInfo)) {
1476 case HND_INVALID:
1477 HandleUnlock();
1478 return UPNP_E_INVALID_HANDLE;
1479 default:
1480 break;
1481 }
1482 /* clean up search list */
1483 node = ListHead(&HInfo->SsdpSearchList);
1484 while (node != NULL) {
1485 searchArg = (SsdpSearchArg*)node->item;
1486 if (searchArg) {
1487 free(searchArg->searchTarget);
1488 free(searchArg);
1489 }
1490 ListDelNode(&HInfo->SsdpSearchList, node, 0);
1491 node = ListHead(&HInfo->SsdpSearchList);
1492 }
1493 ListDestroy(&HInfo->SsdpSearchList, 0);
1494 FreeHandle(Hnd);
1496 HandleUnlock();
1497
1498 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1499 "Exiting UpnpUnRegisterClient \n");
1500
1501 return UPNP_E_SUCCESS;
1502}
1503#endif // COMPA_HAVE_CTRLPT_SSDP
1504
1505#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1513 char* name,
1515 char** alias) {
1516 char* ext;
1517 char* al;
1518
1519 ext = strrchr(name, '.');
1520 if (ext == NULL || strcasecmp(ext, ".xml") != 0) {
1521 return UPNP_E_EXT_NOT_XML;
1522 }
1523
1524 al = strrchr(name, '/');
1525 if (al == NULL) {
1526 *alias = name;
1527 } else {
1528 *alias = al;
1529 }
1530
1531 return UPNP_E_SUCCESS;
1532}
1533
1539 struct sockaddr* serverAddr) {
1540 struct sockaddr_in* sa4 = (struct sockaddr_in*)serverAddr;
1541
1542 memset(serverAddr, 0, sizeof(struct sockaddr_storage));
1543
1544 sa4->sin_family = AF_INET;
1545 inet_pton(AF_INET, gIF_IPV4, &sa4->sin_addr);
1546 sa4->sin_port = htons(LOCAL_PORT_V4);
1547}
1548
1554 struct sockaddr* serverAddr) {
1555 struct sockaddr_in6* sa6 = (struct sockaddr_in6*)serverAddr;
1556
1557 memset(serverAddr, 0, sizeof(struct sockaddr_storage));
1558
1559 sa6->sin6_family = AF_INET6;
1560 inet_pton(AF_INET6, gIF_IPV6, &sa6->sin6_addr);
1561 sa6->sin6_port = htons(LOCAL_PORT_V6);
1562}
1563#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1564
1565#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1566static int GetDescDocumentAndURL(Upnp_DescType descriptionType,
1567 char* description, int config_baseURL,
1568 int AddressFamily, IXML_Document** xmlDoc,
1569 char descURL[LINE_SIZE]) {
1570 int retVal = 0;
1571 char* membuf = NULL;
1572 char aliasStr[LINE_SIZE];
1573 char* temp_str = NULL;
1574 FILE* fp = NULL;
1575 int fd;
1576 size_t fileLen;
1577 size_t num_read;
1578 time_t last_modified{};
1579 struct stat file_info;
1580 struct sockaddr_storage serverAddr;
1581 int rc = UPNP_E_SUCCESS;
1582
1583 memset(aliasStr, 0, sizeof(aliasStr));
1584 if (description == NULL)
1585 return UPNP_E_INVALID_PARAM;
1586 /* non-URL description must have configuration specified */
1587 if (descriptionType != (enum Upnp_DescType_e)UPNPREG_URL_DESC &&
1588 !config_baseURL)
1589 return UPNP_E_INVALID_PARAM;
1590 /* Get XML doc and last modified time */
1591 if (descriptionType == (enum Upnp_DescType_e)UPNPREG_URL_DESC) {
1592 retVal = UpnpDownloadXmlDoc(description, xmlDoc);
1593 if (retVal != UPNP_E_SUCCESS)
1594 return retVal;
1595 last_modified = time(NULL);
1596 } else if (descriptionType == (enum Upnp_DescType_e)UPNPREG_FILENAME_DESC) {
1597 int ret = 0;
1598
1599#ifdef _WIN32
1600 umock::stdio_h.fopen_s(&fp, description, "rb");
1601#else
1602 fp = umock::stdio_h.fopen(description, "rb");
1603#endif
1604 if (!fp) {
1606 ret = 1;
1607 goto exit_function1;
1608 }
1609 fd = fileno(fp);
1610 if (fd == -1) {
1612 ret = 1;
1613 goto exit_function1;
1614 }
1615 retVal = fstat(fd, &file_info);
1616 if (retVal == -1) {
1618 ret = 1;
1619 goto exit_function1;
1620 }
1621 fileLen = (size_t)file_info.st_size;
1622 last_modified = file_info.st_mtime;
1623 membuf = (char*)malloc(fileLen + (size_t)1);
1624 if (!membuf) {
1626 ret = 1;
1627 goto exit_function1;
1628 }
1629 num_read = umock::stdio_h.fread(membuf, (size_t)1, fileLen, fp);
1630 if (num_read != fileLen) {
1632 ret = 1;
1633 goto exit_function2;
1634 }
1635 membuf[fileLen] = 0;
1636 rc = ixmlParseBufferEx(membuf, xmlDoc);
1637 exit_function2:
1638 if (membuf) {
1639 free(membuf);
1640 }
1641 exit_function1:
1642 if (fp) {
1643 umock::stdio_h.fclose(fp);
1644 }
1645 if (ret) {
1646 return rc;
1647 }
1648 } else if (descriptionType == (enum Upnp_DescType_e)UPNPREG_BUF_DESC) {
1649 last_modified = time(NULL);
1650 rc = ixmlParseBufferEx(description, xmlDoc);
1651 } else {
1652 return UPNP_E_INVALID_PARAM;
1653 }
1654
1655 if (rc != IXML_SUCCESS &&
1656 descriptionType != (enum Upnp_DescType_e)UPNPREG_URL_DESC) {
1657 if (rc == IXML_INSUFFICIENT_MEMORY)
1658 return UPNP_E_OUTOF_MEMORY;
1659 else
1660 return UPNP_E_INVALID_DESC;
1661 }
1662 /* Determine alias */
1663 if (config_baseURL) {
1664 if (descriptionType == (enum Upnp_DescType_e)UPNPREG_BUF_DESC) {
1665 strncpy(aliasStr, "description.xml", sizeof(aliasStr) - 1);
1666 } else {
1667 /* URL or filename */
1668 retVal = GetNameForAlias(description, &temp_str);
1669 if (retVal != UPNP_E_SUCCESS) {
1670 ixmlDocument_free(*xmlDoc);
1671 return retVal;
1672 }
1673 if (strlen(temp_str) > (LINE_SIZE - 1)) {
1674 ixmlDocument_free(*xmlDoc);
1675 return UPNP_E_URL_TOO_BIG;
1676 }
1677 strncpy(aliasStr, temp_str, sizeof(aliasStr) - 1);
1678 }
1679 if (AddressFamily == AF_INET) {
1680 get_server_addr((struct sockaddr*)&serverAddr);
1681 } else {
1682 get_server_addr6((struct sockaddr*)&serverAddr);
1683 }
1684
1685 /* config */
1686 retVal = configure_urlbase(*xmlDoc, (struct sockaddr*)&serverAddr,
1687 aliasStr, last_modified, descURL);
1688 if (retVal != UPNP_E_SUCCESS) {
1689 ixmlDocument_free(*xmlDoc);
1690 return retVal;
1691 }
1692 } else {
1693 /* Manual */
1694 if (strlen(description) > LINE_SIZE - 1) {
1695 ixmlDocument_free(*xmlDoc);
1696 return UPNP_E_URL_TOO_BIG;
1697 }
1698 strncpy(descURL, description, LINE_SIZE - 1);
1699 descURL[LINE_SIZE - 1] = '\0';
1700 }
1701
1702 assert(*xmlDoc != NULL);
1703
1704 return UPNP_E_SUCCESS;
1705}
1706#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1707
1708/*******************************************************************************
1709 *
1710 * SSDP interface
1711 *
1712 ******************************************************************************/
1713
1714#ifdef COMPA_HAVE_DEVICE_SSDP
1716 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1717 "Inside UpnpSendAdvertisement \n");
1718 return UpnpSendAdvertisementLowPower(Hnd, Exp, -1, -1, -1);
1719}
1720
1722 int PowerState, int SleepPeriod,
1723 int RegistrationState) {
1724 struct Handle_Info* SInfo = NULL;
1725 int retVal = 0, *ptrMx;
1726 job_arg* adEvent;
1727 ThreadPoolJob job;
1728
1729 memset(&job, 0, sizeof(job));
1730
1731 if (UpnpSdkInit != 1) {
1732 return UPNP_E_FINISH;
1733 }
1734
1735 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1736 "Inside UpnpSendAdvertisementLowPower \n");
1737
1738 HandleLock();
1739 switch (GetHandleInfo(Hnd, &SInfo)) {
1740 case HND_DEVICE:
1741 break;
1742 default:
1743 HandleUnlock();
1744 return UPNP_E_INVALID_HANDLE;
1745 }
1746 if (Exp < 1)
1747 Exp = DEFAULT_MAXAGE;
1748 if (Exp <= AUTO_ADVERTISEMENT_TIME * 2)
1749 Exp = (AUTO_ADVERTISEMENT_TIME + 1) * 2;
1750 SInfo->MaxAge = Exp;
1751 SInfo->PowerState = PowerState;
1752 if (SleepPeriod < 0)
1753 SleepPeriod = -1;
1754 SInfo->SleepPeriod = SleepPeriod;
1756 HandleUnlock();
1757 retVal = AdvertiseAndReply(1, Hnd, (enum SsdpSearchType)0,
1758 (struct sockaddr*)NULL, (char*)NULL, (char*)NULL,
1759 (char*)NULL, Exp);
1760
1761 if (retVal != UPNP_E_SUCCESS)
1762 return retVal;
1763 ptrMx = (int*)malloc(sizeof(int));
1764 if (ptrMx == NULL)
1765 return UPNP_E_OUTOF_MEMORY;
1766 adEvent = (job_arg*)malloc(sizeof(job_arg));
1767
1768 if (adEvent == NULL) {
1769 free(ptrMx);
1770 return UPNP_E_OUTOF_MEMORY;
1771 }
1772 *ptrMx = Exp;
1773 adEvent->advertise.handle = Hnd;
1774 adEvent->advertise.Event = ptrMx;
1775
1776 HandleLock();
1777 switch (GetHandleInfo(Hnd, &SInfo)) {
1778 case HND_DEVICE:
1779 break;
1780 default:
1781 HandleUnlock();
1782 free(adEvent);
1783 free(ptrMx);
1784 return UPNP_E_INVALID_HANDLE;
1785 }
1786#ifdef SSDP_PACKET_DISTRIBUTE
1787 TPJobInit(&job, (UPnPsdk::start_routine)AutoAdvertise, adEvent);
1789 TPJobSetPriority(&job, MED_PRIORITY);
1790 if ((retVal = TimerThreadSchedule(
1791 &gTimerThread, ((Exp / 2) - (AUTO_ADVERTISEMENT_TIME)), REL_SEC,
1792 &job, SHORT_TERM, &(adEvent->advertise.eventId))) !=
1794 HandleUnlock();
1795 free_advertise_arg(adEvent);
1796 return retVal;
1797 }
1798#else
1799 TPJobInit(&job, (UPnPsdk::start_routine)AutoAdvertise, adEvent);
1801 TPJobSetPriority(&job, MED_PRIORITY);
1802 if ((retVal = TimerThreadSchedule(
1804 SHORT_TERM, &(adEvent->advertise.eventId))) != UPNP_E_SUCCESS) {
1805 HandleUnlock();
1806 free_advertise_arg(adEvent);
1807 return retVal;
1808 }
1809#endif
1810
1811 HandleUnlock();
1812 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1813 "Exiting UpnpSendAdvertisementLowPower \n");
1814
1815 return retVal;
1816}
1817#endif /* COMPA_HAVE_DEVICE_SSDP */
1818
1819#ifdef COMPA_HAVE_CTRLPT_SSDP
1820int UpnpSearchAsync(UpnpClient_Handle Hnd, int Mx, const char* Target_const,
1821 const void* Cookie_const) {
1822 struct Handle_Info* SInfo = NULL;
1823 char* Target = (char*)Target_const;
1824 int retVal;
1825
1826 if (UpnpSdkInit != 1) {
1827 return UPNP_E_FINISH;
1828 }
1829
1830 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSearchAsync\n");
1831
1833 switch (GetHandleInfo(Hnd, &SInfo)) {
1834 case HND_CLIENT:
1835 break;
1836 default:
1837 HandleUnlock();
1838 return UPNP_E_INVALID_HANDLE;
1839 }
1840 if (Mx < 1)
1841 Mx = DEFAULT_MX;
1842
1843 if (Target == NULL) {
1844 HandleUnlock();
1845 return UPNP_E_INVALID_PARAM;
1846 }
1847
1848 HandleUnlock();
1849 retVal = SearchByTarget(Hnd, Mx, Target, (void*)Cookie_const);
1850 if (retVal != 1)
1851 return retVal;
1852
1853 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSearchAsync \n");
1854
1855 return UPNP_E_SUCCESS;
1856}
1857#endif /* COMPA_HAVE_CTRLPT_SSDP */
1858
1859/*******************************************************************************
1860 *
1861 * GENA interface
1862 *
1863 ******************************************************************************/
1864
1865#ifdef COMPA_HAVE_DEVICE_GENA
1867 struct Handle_Info* SInfo = NULL;
1868
1869 if (UpnpSdkInit != 1) {
1870 return UPNP_E_FINISH;
1871 }
1872
1873 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1874 "Inside UpnpSetMaxSubscriptions \n");
1875
1876 HandleLock();
1877 switch (GetHandleInfo(Hnd, &SInfo)) {
1878 case HND_DEVICE:
1879 break;
1880 default:
1881 HandleUnlock();
1882 return UPNP_E_INVALID_HANDLE;
1883 }
1885 HandleUnlock();
1886 return UPNP_E_INVALID_HANDLE;
1887 }
1889 HandleUnlock();
1890
1891 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1892 "Exiting UpnpSetMaxSubscriptions \n");
1893
1894 return UPNP_E_SUCCESS;
1895}
1896#endif /* COMPA_HAVE_DEVICE_GENA */
1897
1898#ifdef COMPA_HAVE_DEVICE_GENA
1901 struct Handle_Info* SInfo = NULL;
1902
1903 if (UpnpSdkInit != 1) {
1904 return UPNP_E_FINISH;
1905 }
1906
1907 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1908 "Inside UpnpSetMaxSubscriptionTimeOut\n");
1909
1910 HandleLock();
1911
1912 switch (GetHandleInfo(Hnd, &SInfo)) {
1913 case HND_DEVICE:
1914 break;
1915 default:
1916 HandleUnlock();
1917 return UPNP_E_INVALID_HANDLE;
1918 }
1920 (MaxSubscriptionTimeOut < 0)) {
1921 HandleUnlock();
1922 return UPNP_E_INVALID_HANDLE;
1923 }
1924
1926 HandleUnlock();
1927
1928 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1929 "Exiting UpnpSetMaxSubscriptionTimeOut\n");
1930
1931 return UPNP_E_SUCCESS;
1932}
1933#endif /* COMPA_HAVE_DEVICE_GENA */
1934
1935#ifdef COMPA_HAVE_CTRLPT_GENA
1936int UpnpSubscribe(UpnpClient_Handle Hnd, const char* EvtUrl_const, int* TimeOut,
1937 Upnp_SID SubsId) {
1938 int retVal;
1939 struct Handle_Info* SInfo = NULL;
1940 UpnpString* EvtUrl = UpnpString_new();
1941 UpnpString* SubsIdTmp = UpnpString_new();
1942
1943 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSubscribe\n");
1944
1945 if (UpnpSdkInit != 1) {
1946 retVal = UPNP_E_FINISH;
1947 goto exit_function;
1948 }
1949
1950 if (EvtUrl == NULL) {
1951 retVal = UPNP_E_OUTOF_MEMORY;
1952 goto exit_function;
1953 }
1954 if (EvtUrl_const == NULL) {
1955 retVal = UPNP_E_INVALID_PARAM;
1956 goto exit_function;
1957 }
1958 UpnpString_set_String(EvtUrl, EvtUrl_const);
1959
1960 if (SubsIdTmp == NULL) {
1961 retVal = UPNP_E_OUTOF_MEMORY;
1962 goto exit_function;
1963 }
1964 if (SubsId == NULL) {
1965 retVal = UPNP_E_INVALID_PARAM;
1966 goto exit_function;
1967 }
1968 UpnpString_set_String(SubsIdTmp, SubsId);
1969
1970 if (TimeOut == NULL) {
1971 retVal = UPNP_E_INVALID_PARAM;
1972 goto exit_function;
1973 }
1974
1976 switch (GetHandleInfo(Hnd, &SInfo)) {
1977 case HND_CLIENT:
1978 break;
1979 default:
1980 HandleUnlock();
1981 retVal = UPNP_E_INVALID_HANDLE;
1982 goto exit_function;
1983 }
1984 HandleUnlock();
1985
1986 retVal = genaSubscribe(Hnd, EvtUrl, TimeOut, SubsIdTmp);
1987 memset(SubsId, 0, sizeof(Upnp_SID));
1988 strncpy(SubsId, UpnpString_get_String(SubsIdTmp), sizeof(Upnp_SID) - 1);
1989
1990exit_function:
1991 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1992 "Exiting UpnpSubscribe, retVal=%d\n", retVal);
1993
1994 UpnpString_delete(SubsIdTmp);
1995 UpnpString_delete(EvtUrl);
1996
1997 return retVal;
1998}
1999#endif /* COMPA_HAVE_CTRLPT_GENA */
2000
2001#ifdef COMPA_HAVE_CTRLPT_GENA
2002int UpnpSubscribeAsync(UpnpClient_Handle Hnd, const char* EvtUrl_const,
2003 int TimeOut, Upnp_FunPtr Fun, const void* Cookie_const) {
2004 struct Handle_Info* SInfo = NULL;
2005 struct UpnpNonblockParam* Param;
2006 char* EvtUrl = (char*)EvtUrl_const;
2007 ThreadPoolJob job;
2008
2009 memset(&job, 0, sizeof(job));
2010
2011 if (UpnpSdkInit != 1) {
2012 return UPNP_E_FINISH;
2013 }
2014
2015 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2016 "Inside UpnpSubscribeAsync\n");
2017
2019 switch (GetHandleInfo(Hnd, &SInfo)) {
2020 case HND_CLIENT:
2021 break;
2022 default:
2023 HandleUnlock();
2024 return UPNP_E_INVALID_HANDLE;
2025 }
2026 if (EvtUrl == NULL) {
2027 HandleUnlock();
2028 return UPNP_E_INVALID_PARAM;
2029 }
2030 if (TimeOut != UPNP_INFINITE && TimeOut < 1) {
2031 HandleUnlock();
2032 return UPNP_E_INVALID_PARAM;
2033 }
2034 if (Fun == NULL) {
2035 HandleUnlock();
2036 return UPNP_E_INVALID_PARAM;
2037 }
2038 HandleUnlock();
2039
2040 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2041 if (Param == NULL) {
2042 return UPNP_E_OUTOF_MEMORY;
2043 }
2044 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2045
2046 Param->FunName = SUBSCRIBE;
2047 Param->Handle = Hnd;
2048 strncpy(Param->Url, EvtUrl, sizeof(Param->Url) - 1);
2049 Param->TimeOut = TimeOut;
2050 Param->Fun = Fun;
2051 Param->Cookie = (char*)Cookie_const;
2052
2053 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2055 TPJobSetPriority(&job, MED_PRIORITY);
2056 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2057 free(Param);
2058 }
2059
2060 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2061 "Exiting UpnpSubscribeAsync\n");
2062
2063 return UPNP_E_SUCCESS;
2064}
2065#endif /* COMPA_HAVE_CTRLPT_GENA */
2066
2067#ifdef COMPA_HAVE_CTRLPT_GENA
2069 struct Handle_Info* SInfo = NULL;
2070 int retVal;
2071 UpnpString* SubsIdTmp = UpnpString_new();
2072
2073 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpUnSubscribe\n");
2074
2075 if (UpnpSdkInit != 1) {
2076 retVal = UPNP_E_FINISH;
2077 goto exit_function;
2078 }
2079
2080 if (SubsIdTmp == NULL) {
2081 retVal = UPNP_E_OUTOF_MEMORY;
2082 goto exit_function;
2083 }
2084 if (SubsId == NULL) {
2085 retVal = UPNP_E_INVALID_PARAM;
2086 goto exit_function;
2087 }
2088 UpnpString_set_String(SubsIdTmp, SubsId);
2089
2091 switch (GetHandleInfo(Hnd, &SInfo)) {
2092 case HND_CLIENT:
2093 break;
2094 default:
2095 HandleUnlock();
2096 retVal = UPNP_E_INVALID_HANDLE;
2097 goto exit_function;
2098 }
2099 HandleUnlock();
2100
2101 retVal = genaUnSubscribe(Hnd, SubsIdTmp);
2102
2103exit_function:
2104 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2105 "Exiting UpnpUnSubscribe, retVal=%d\n", retVal);
2106
2107 UpnpString_delete(SubsIdTmp);
2108
2109 return retVal;
2110}
2111#endif /* COMPA_HAVE_CTRLPT_GENA */
2112
2113#ifdef COMPA_HAVE_CTRLPT_GENA
2115 Upnp_FunPtr Fun, const void* Cookie_const) {
2116 int retVal = UPNP_E_SUCCESS;
2117 ThreadPoolJob job;
2118 struct Handle_Info* SInfo = NULL;
2119 struct UpnpNonblockParam* Param;
2120
2121 memset(&job, 0, sizeof(job));
2122
2123 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2124 "Inside UpnpUnSubscribeAsync\n");
2125
2126 if (UpnpSdkInit != 1) {
2127 retVal = UPNP_E_FINISH;
2128 goto exit_function;
2129 }
2130
2131 if (SubsId == NULL) {
2132 retVal = UPNP_E_INVALID_PARAM;
2133 goto exit_function;
2134 }
2135 if (Fun == NULL) {
2136 retVal = UPNP_E_INVALID_PARAM;
2137 goto exit_function;
2138 }
2139
2141 switch (GetHandleInfo(Hnd, &SInfo)) {
2142 case HND_CLIENT:
2143 break;
2144 default:
2145 HandleUnlock();
2146 retVal = UPNP_E_INVALID_HANDLE;
2147 goto exit_function;
2148 }
2149 HandleUnlock();
2150
2151 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2152 if (Param == NULL) {
2153 retVal = UPNP_E_OUTOF_MEMORY;
2154 goto exit_function;
2155 }
2156 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2157
2158 Param->FunName = UNSUBSCRIBE;
2159 Param->Handle = Hnd;
2160 strncpy(Param->SubsId, SubsId, sizeof(Param->SubsId) - 1);
2161 Param->Fun = Fun;
2162 Param->Cookie = (char*)Cookie_const;
2163 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2165 TPJobSetPriority(&job, MED_PRIORITY);
2166 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2167 free(Param);
2168 }
2169
2170exit_function:
2171 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2172 "Exiting UpnpUnSubscribeAsync\n");
2173
2174 return retVal;
2175}
2176#endif /* COMPA_HAVE_CTRLPT_GENA */
2177
2178#ifdef COMPA_HAVE_CTRLPT_GENA
2180 const Upnp_SID SubsId) {
2181 struct Handle_Info* SInfo = NULL;
2182 int retVal;
2183 UpnpString* SubsIdTmp = UpnpString_new();
2184
2185 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2186 "Inside UpnpRenewSubscription\n");
2187
2188 if (UpnpSdkInit != 1) {
2189 retVal = UPNP_E_FINISH;
2190 goto exit_function;
2191 }
2192
2193 if (SubsIdTmp == NULL) {
2194 retVal = UPNP_E_OUTOF_MEMORY;
2195 goto exit_function;
2196 }
2197 if (SubsId == NULL) {
2198 retVal = UPNP_E_INVALID_PARAM;
2199 goto exit_function;
2200 }
2201 UpnpString_set_String(SubsIdTmp, SubsId);
2202
2203 if (TimeOut == NULL) {
2204 retVal = UPNP_E_INVALID_PARAM;
2205 goto exit_function;
2206 }
2207
2209 switch (GetHandleInfo(Hnd, &SInfo)) {
2210 case HND_CLIENT:
2211 break;
2212 default:
2213 HandleUnlock();
2214 retVal = UPNP_E_INVALID_HANDLE;
2215 goto exit_function;
2216 }
2217 HandleUnlock();
2218
2219 retVal = genaRenewSubscription(Hnd, SubsIdTmp, TimeOut);
2220
2221exit_function:
2222 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2223 "Exiting UpnpRenewSubscription, retVal=%d\n", retVal);
2224
2225 UpnpString_delete(SubsIdTmp);
2226
2227 return retVal;
2228}
2229#endif /* COMPA_HAVE_CTRLPT_GENA */
2230
2231#ifdef COMPA_HAVE_CTRLPT_GENA
2233 Upnp_SID SubsId, Upnp_FunPtr Fun,
2234 const void* Cookie_const) {
2235 ThreadPoolJob job;
2236 struct Handle_Info* SInfo = NULL;
2237 struct UpnpNonblockParam* Param;
2238
2239 memset(&job, 0, sizeof(job));
2240
2241 if (UpnpSdkInit != 1) {
2242 return UPNP_E_FINISH;
2243 }
2244
2245 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2246 "Inside UpnpRenewSubscriptionAsync\n");
2248 switch (GetHandleInfo(Hnd, &SInfo)) {
2249 case HND_CLIENT:
2250 break;
2251 default:
2252 HandleUnlock();
2253 return UPNP_E_INVALID_HANDLE;
2254 }
2255 if (TimeOut != UPNP_INFINITE && TimeOut < 1) {
2256 HandleUnlock();
2257 return UPNP_E_INVALID_PARAM;
2258 }
2259 if (SubsId == NULL) {
2260 HandleUnlock();
2261 return UPNP_E_INVALID_PARAM;
2262 }
2263 if (Fun == NULL) {
2264 HandleUnlock();
2265 return UPNP_E_INVALID_PARAM;
2266 }
2267 HandleUnlock();
2268
2269 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2270 if (Param == NULL) {
2271 return UPNP_E_OUTOF_MEMORY;
2272 }
2273 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2274
2275 Param->FunName = RENEW;
2276 Param->Handle = Hnd;
2277 strncpy(Param->SubsId, SubsId, sizeof(Param->SubsId) - 1);
2278 Param->Fun = Fun;
2279 Param->Cookie = (char*)Cookie_const;
2280 Param->TimeOut = TimeOut;
2281
2282 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2284 TPJobSetPriority(&job, MED_PRIORITY);
2285 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2286 free(Param);
2287 }
2288
2289 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2290 "Exiting UpnpRenewSubscriptionAsync\n");
2291
2292 return UPNP_E_SUCCESS;
2293}
2294#endif /* COMPA_HAVE_CTRLPT_GENA */
2295
2296#ifdef COMPA_HAVE_DEVICE_GENA
2297int UpnpNotify(UpnpDevice_Handle Hnd, const char* DevID_const,
2298 const char* ServName_const, const char** VarName_const,
2299 const char** NewVal_const, int cVariables) {
2300 struct Handle_Info* SInfo = NULL;
2301 int retVal;
2302 char* DevID = (char*)DevID_const;
2303 char* ServName = (char*)ServName_const;
2304 char** VarName = (char**)VarName_const;
2305 char** NewVal = (char**)NewVal_const;
2306
2307 if (UpnpSdkInit != 1) {
2308 return UPNP_E_FINISH;
2309 }
2310
2311 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpNotify\n");
2312
2314 switch (GetHandleInfo(Hnd, &SInfo)) {
2315 case HND_DEVICE:
2316 break;
2317 default:
2318 HandleUnlock();
2319 return UPNP_E_INVALID_HANDLE;
2320 }
2321 if (DevID == NULL) {
2322 HandleUnlock();
2323 return UPNP_E_INVALID_PARAM;
2324 }
2325 if (ServName == NULL) {
2326 HandleUnlock();
2327 return UPNP_E_INVALID_PARAM;
2328 }
2329 if (VarName == NULL || NewVal == NULL || cVariables < 0) {
2330 HandleUnlock();
2331 return UPNP_E_INVALID_PARAM;
2332 }
2333
2334 HandleUnlock();
2335 retVal = genaNotifyAll(Hnd, DevID, ServName, VarName, NewVal, cVariables);
2336
2337 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpNotify\n");
2338
2339 return retVal;
2340}
2341
2342int UpnpNotifyExt(UpnpDevice_Handle Hnd, const char* DevID_const,
2343 const char* ServName_const, IXML_Document* PropSet) {
2344 struct Handle_Info* SInfo = NULL;
2345 int retVal;
2346 char* DevID = (char*)DevID_const;
2347 char* ServName = (char*)ServName_const;
2348
2349 if (UpnpSdkInit != 1) {
2350 return UPNP_E_FINISH;
2351 }
2352
2353 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpNotify \n");
2354
2356 switch (GetHandleInfo(Hnd, &SInfo)) {
2357 case HND_DEVICE:
2358 break;
2359 default:
2360 HandleUnlock();
2361 return UPNP_E_INVALID_HANDLE;
2362 }
2363 if (DevID == NULL) {
2364 HandleUnlock();
2365 return UPNP_E_INVALID_PARAM;
2366 }
2367 if (ServName == NULL) {
2368 HandleUnlock();
2369 return UPNP_E_INVALID_PARAM;
2370 }
2371
2372 HandleUnlock();
2373 retVal = genaNotifyAllExt(Hnd, DevID, ServName, PropSet);
2374
2375 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpNotify \n");
2376
2377 return retVal;
2378}
2379#endif /* COMPA_HAVE_DEVICE_GENA */
2380
2381#ifdef COMPA_HAVE_DEVICE_GENA
2382int UpnpAcceptSubscription(UpnpDevice_Handle Hnd, const char* DevID_const,
2383 const char* ServName_const,
2384 const char** VarName_const,
2385 const char** NewVal_const, int cVariables,
2386 const Upnp_SID SubsId) {
2387 int ret = 0;
2388 int line = 0;
2389 struct Handle_Info* SInfo = NULL;
2390 char* DevID = (char*)DevID_const;
2391 char* ServName = (char*)ServName_const;
2392 char** VarName = (char**)VarName_const;
2393 char** NewVal = (char**)NewVal_const;
2394
2395 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2396 "Inside UpnpAcceptSubscription\n");
2397
2398 if (UpnpSdkInit != 1) {
2399 line = __LINE__;
2400 ret = UPNP_E_FINISH;
2401 goto exit_function;
2402 }
2403
2405
2406 switch (GetHandleInfo(Hnd, &SInfo)) {
2407 case HND_DEVICE:
2408 break;
2409 default:
2410 HandleUnlock();
2411 line = __LINE__;
2413 goto exit_function;
2414 }
2415 if (DevID == NULL) {
2416 HandleUnlock();
2417 line = __LINE__;
2419 goto exit_function;
2420 }
2421 if (ServName == NULL) {
2422 HandleUnlock();
2423 line = __LINE__;
2425 goto exit_function;
2426 }
2427 if (SubsId == NULL) {
2428 HandleUnlock();
2429 line = __LINE__;
2431 goto exit_function;
2432 }
2433/* Now accepts an empty state list, so the code below is
2434 * commented out */
2435#if 0
2436 if (VarName == NULL || NewVal == NULL || cVariables < 0) {
2437 HandleUnlock();
2438 line = __LINE__;
2440 goto exit_function;
2441 }
2442#endif
2443
2444 HandleUnlock();
2445
2446 line = __LINE__;
2447 ret = genaInitNotify(Hnd, DevID, ServName, VarName, NewVal, cVariables,
2448 SubsId);
2449
2450exit_function:
2451 UpnpPrintf(UPNP_ALL, API, __FILE__, line,
2452 "Exiting UpnpAcceptSubscription, ret = %d\n", ret);
2453
2454 return ret;
2455}
2456
2457int UpnpAcceptSubscriptionExt(UpnpDevice_Handle Hnd, const char* DevID_const,
2458 const char* ServName_const,
2459 IXML_Document* PropSet, const Upnp_SID SubsId) {
2460 int ret = 0;
2461 int line = 0;
2462 struct Handle_Info* SInfo = NULL;
2463 char* DevID = (char*)DevID_const;
2464 char* ServName = (char*)ServName_const;
2465
2466 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2467 "Inside UpnpAcceptSubscription\n");
2468
2469 if (UpnpSdkInit != 1) {
2470 line = __LINE__;
2471 ret = UPNP_E_FINISH;
2472 goto exit_function;
2473 }
2474
2476
2477 switch (GetHandleInfo(Hnd, &SInfo)) {
2478 case HND_DEVICE:
2479 break;
2480 default:
2481 HandleUnlock();
2482 line = __LINE__;
2484 goto exit_function;
2485 }
2486 if (DevID == NULL) {
2487 HandleUnlock();
2488 line = __LINE__;
2490 goto exit_function;
2491 }
2492 if (ServName == NULL) {
2493 HandleUnlock();
2494 line = __LINE__;
2496 goto exit_function;
2497 }
2498 if (SubsId == NULL) {
2499 HandleUnlock();
2500 line = __LINE__;
2502 goto exit_function;
2503 }
2504/* Now accepts an empty state list, so the code below is
2505 * commented out */
2506#if 0
2507 if (PropSet == NULL) {
2508 HandleUnlock();
2509 line = __LINE__;
2511 goto exit_function;
2512 }
2513#endif
2514
2515 HandleUnlock();
2516
2517 line = __LINE__;
2518 ret = genaInitNotifyExt(Hnd, DevID, ServName, PropSet, SubsId);
2519
2520exit_function:
2521 UpnpPrintf(UPNP_ALL, API, __FILE__, line,
2522 "Exiting UpnpAcceptSubscription, ret = %d.\n", ret);
2523
2524 return ret;
2525}
2526#endif /* COMPA_HAVE_DEVICE_GENA */
2527
2528/*******************************************************************************
2529 *
2530 * SOAP interface
2531 *
2532 ******************************************************************************/
2533
2534#ifdef COMPA_HAVE_CTRLPT_SOAP
2535int UpnpSendAction(UpnpClient_Handle Hnd, const char* ActionURL_const,
2536 const char* ServiceType_const, const char* DevUDN_const,
2537 IXML_Document* Action, IXML_Document** RespNodePtr) {
2538 struct Handle_Info* SInfo = NULL;
2539 int retVal = 0;
2540 char* ActionURL = (char*)ActionURL_const;
2541 char* ServiceType = (char*)ServiceType_const;
2542 /* udn not used? */
2543 /*char *DevUDN = (char *)DevUDN_const;*/
2544
2545 if (UpnpSdkInit != 1) {
2546 return UPNP_E_FINISH;
2547 }
2548
2549 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSendAction\n");
2550 if (DevUDN_const != NULL) {
2551 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2552 "non NULL DevUDN is ignored\n");
2553 }
2554 DevUDN_const = NULL;
2555
2557 switch (GetHandleInfo(Hnd, &SInfo)) {
2558 case HND_CLIENT:
2559 break;
2560 default:
2561 HandleUnlock();
2562 return UPNP_E_INVALID_HANDLE;
2563 }
2564 HandleUnlock();
2565
2566 if (ActionURL == NULL) {
2567 return UPNP_E_INVALID_PARAM;
2568 }
2569
2570 if (ServiceType == NULL || Action == NULL || RespNodePtr == NULL ||
2571 DevUDN_const != NULL) {
2572
2573 return UPNP_E_INVALID_PARAM;
2574 }
2575
2576 retVal = SoapSendAction(ActionURL, ServiceType, Action, RespNodePtr);
2577
2578 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSendAction\n");
2579
2580 return retVal;
2581}
2582
2583int UpnpSendActionEx(UpnpClient_Handle Hnd, const char* ActionURL_const,
2584 const char* ServiceType_const, const char* DevUDN_const,
2585 IXML_Document* Header, IXML_Document* Action,
2586 IXML_Document** RespNodePtr) {
2587 struct Handle_Info* SInfo = NULL;
2588 int retVal = 0;
2589 char* ActionURL = (char*)ActionURL_const;
2590 char* ServiceType = (char*)ServiceType_const;
2591 /* udn not used? */
2592 /*char *DevUDN = (char *)DevUDN_const;*/
2593
2594 if (UpnpSdkInit != 1) {
2595 return UPNP_E_FINISH;
2596 }
2597
2598 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSendActionEx\n");
2599
2600 if (Header == NULL) {
2601 retVal = UpnpSendAction(Hnd, ActionURL_const, ServiceType_const,
2602 DevUDN_const, Action, RespNodePtr);
2603 return retVal;
2604 }
2605
2607 switch (GetHandleInfo(Hnd, &SInfo)) {
2608 case HND_CLIENT:
2609 break;
2610 default:
2611 HandleUnlock();
2612 return UPNP_E_INVALID_HANDLE;
2613 }
2614 HandleUnlock();
2615
2616 if (ActionURL == NULL) {
2617 return UPNP_E_INVALID_PARAM;
2618 }
2619 if (ServiceType == NULL || Action == NULL || RespNodePtr == NULL) {
2620 return UPNP_E_INVALID_PARAM;
2621 }
2622
2623 retVal =
2624 SoapSendActionEx(ActionURL, ServiceType, Header, Action, RespNodePtr);
2625
2626 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSendAction \n");
2627
2628 return retVal;
2629}
2630
2631int UpnpSendActionAsync(UpnpClient_Handle Hnd, const char* ActionURL_const,
2632 const char* ServiceType_const, const char* DevUDN_const,
2633 IXML_Document* Act, Upnp_FunPtr Fun,
2634 const void* Cookie_const) {
2635 int rc;
2636 ThreadPoolJob job;
2637 struct Handle_Info* SInfo = NULL;
2638 struct UpnpNonblockParam* Param;
2639 DOMString tmpStr;
2640 char* ActionURL = (char*)ActionURL_const;
2641 char* ServiceType = (char*)ServiceType_const;
2642 /* udn not used? */
2643 /*char *DevUDN = (char *)DevUDN_const;*/
2644
2645 memset(&job, 0, sizeof(job));
2646
2647 if (UpnpSdkInit != 1) {
2648 return UPNP_E_FINISH;
2649 }
2650
2651 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2652 "Inside UpnpSendActionAsync\n");
2653
2655 switch (GetHandleInfo(Hnd, &SInfo)) {
2656 case HND_CLIENT:
2657 break;
2658 default:
2659 HandleUnlock();
2660 return UPNP_E_INVALID_HANDLE;
2661 }
2662 HandleUnlock();
2663
2664 if (ActionURL == NULL) {
2665 return UPNP_E_INVALID_PARAM;
2666 }
2667 if (ServiceType == NULL || Act == NULL || Fun == NULL ||
2668 DevUDN_const != NULL) {
2669 return UPNP_E_INVALID_PARAM;
2670 }
2671 tmpStr = ixmlPrintNode((IXML_Node*)Act);
2672 if (tmpStr == NULL) {
2673 return UPNP_E_INVALID_ACTION;
2674 }
2675
2676 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2677
2678 if (Param == NULL) {
2679 ixmlFreeDOMString(tmpStr);
2680 return UPNP_E_OUTOF_MEMORY;
2681 }
2682 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2683
2684 Param->FunName = ACTION;
2685 Param->Handle = Hnd;
2686 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2687 strncpy(Param->ServiceType, ServiceType, sizeof(Param->ServiceType) - 1);
2688
2689 rc = ixmlParseBufferEx(tmpStr, &(Param->Act));
2690 if (rc != IXML_SUCCESS) {
2691 free(Param);
2692 ixmlFreeDOMString(tmpStr);
2693 if (rc == IXML_INSUFFICIENT_MEMORY) {
2694 return UPNP_E_OUTOF_MEMORY;
2695 } else {
2696 return UPNP_E_INVALID_ACTION;
2697 }
2698 }
2699 ixmlFreeDOMString(tmpStr);
2700 Param->Cookie = (char*)Cookie_const;
2701 Param->Fun = Fun;
2702
2703 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2705
2706 TPJobSetPriority(&job, MED_PRIORITY);
2707 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2708 free_action_arg((job_arg*)Param);
2709 }
2710
2711 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2712 "Exiting UpnpSendActionAsync \n");
2713
2714 return UPNP_E_SUCCESS;
2715}
2716
2717int UpnpSendActionExAsync(UpnpClient_Handle Hnd, const char* ActionURL_const,
2718 const char* ServiceType_const,
2719 const char* DevUDN_const, IXML_Document* Header,
2721 const void* Cookie_const) {
2722 struct Handle_Info* SInfo = NULL;
2723 struct UpnpNonblockParam* Param;
2724 DOMString tmpStr;
2725 DOMString headerStr = NULL;
2726 char* ActionURL = (char*)ActionURL_const;
2727 char* ServiceType = (char*)ServiceType_const;
2728 ThreadPoolJob job;
2729 int retVal = 0;
2730
2731 memset(&job, 0, sizeof(job));
2732
2733 if (UpnpSdkInit != 1) {
2734 return UPNP_E_FINISH;
2735 }
2736
2737 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2738 "Inside UpnpSendActionExAsync\n");
2739
2740 if (Header == NULL) {
2741 retVal = UpnpSendActionAsync(Hnd, ActionURL_const, ServiceType_const,
2742 DevUDN_const, Act, Fun, Cookie_const);
2743 return retVal;
2744 }
2745
2747 switch (GetHandleInfo(Hnd, &SInfo)) {
2748 case HND_CLIENT:
2749 break;
2750 default:
2751 HandleUnlock();
2752 return UPNP_E_INVALID_HANDLE;
2753 }
2754 HandleUnlock();
2755
2756 if (ActionURL == NULL) {
2757 return UPNP_E_INVALID_PARAM;
2758 }
2759 if (ServiceType == NULL || Act == NULL || Fun == NULL) {
2760 return UPNP_E_INVALID_PARAM;
2761 }
2762
2763 headerStr = ixmlPrintNode((IXML_Node*)Header);
2764
2765 tmpStr = ixmlPrintNode((IXML_Node*)Act);
2766 if (tmpStr == NULL) {
2767 ixmlFreeDOMString(headerStr);
2768 return UPNP_E_INVALID_ACTION;
2769 }
2770
2771 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2772 if (Param == NULL) {
2773 ixmlFreeDOMString(tmpStr);
2774 ixmlFreeDOMString(headerStr);
2775 return UPNP_E_OUTOF_MEMORY;
2776 }
2777 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2778
2779 Param->FunName = ACTION;
2780 Param->Handle = Hnd;
2781 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2782 strncpy(Param->ServiceType, ServiceType, sizeof(Param->ServiceType) - 1);
2783 retVal = ixmlParseBufferEx(headerStr, &(Param->Header));
2784 if (retVal != IXML_SUCCESS) {
2785 free(Param);
2786 ixmlFreeDOMString(tmpStr);
2787 ixmlFreeDOMString(headerStr);
2788 if (retVal == IXML_INSUFFICIENT_MEMORY) {
2789 return UPNP_E_OUTOF_MEMORY;
2790 } else {
2791 return UPNP_E_INVALID_ACTION;
2792 }
2793 }
2794
2795 retVal = ixmlParseBufferEx(tmpStr, &(Param->Act));
2796 if (retVal != IXML_SUCCESS) {
2797 ixmlDocument_free(Param->Header);
2798 free(Param);
2799 ixmlFreeDOMString(tmpStr);
2800 ixmlFreeDOMString(headerStr);
2801 if (retVal == IXML_INSUFFICIENT_MEMORY) {
2802 return UPNP_E_OUTOF_MEMORY;
2803 } else {
2804 return UPNP_E_INVALID_ACTION;
2805 }
2806 }
2807
2808 ixmlFreeDOMString(tmpStr);
2809 ixmlFreeDOMString(headerStr);
2810
2811 Param->Cookie = (char*)Cookie_const;
2812 Param->Fun = Fun;
2813
2814 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2816
2817 TPJobSetPriority(&job, MED_PRIORITY);
2818 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2819 free_action_arg((job_arg*)Param);
2820 }
2821
2822 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2823 "Exiting UpnpSendActionAsync\n");
2824
2825 return UPNP_E_SUCCESS;
2826}
2827
2828// Deprecated
2830 const char* ActionURL_const,
2831 const char* VarName_const, Upnp_FunPtr Fun,
2832 const void* Cookie_const) {
2833 ThreadPoolJob job;
2834 struct Handle_Info* SInfo = NULL;
2835 struct UpnpNonblockParam* Param;
2836 char* ActionURL = (char*)ActionURL_const;
2837 char* VarName = (char*)VarName_const;
2838
2839 memset(&job, 0, sizeof(job));
2840
2841 if (UpnpSdkInit != 1) {
2842 return UPNP_E_FINISH;
2843 }
2844
2845 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2846 "Inside UpnpGetServiceVarStatusAsync\n");
2847
2849 switch (GetHandleInfo(Hnd, &SInfo)) {
2850 case HND_CLIENT:
2851 break;
2852 default:
2853 HandleUnlock();
2854 return UPNP_E_INVALID_HANDLE;
2855 }
2856 HandleUnlock();
2857
2858 if (ActionURL == NULL) {
2859 return UPNP_E_INVALID_PARAM;
2860 }
2861 if (VarName == NULL || Fun == NULL)
2862 return UPNP_E_INVALID_PARAM;
2863
2864 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2865 if (Param == NULL) {
2866 return UPNP_E_OUTOF_MEMORY;
2867 }
2868 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2869
2870 Param->FunName = STATUS;
2871 Param->Handle = Hnd;
2872 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2873 strncpy(Param->VarName, VarName, sizeof(Param->VarName) - 1);
2874 Param->Fun = Fun;
2875 Param->Cookie = (char*)Cookie_const;
2876
2877 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2879
2880 TPJobSetPriority(&job, MED_PRIORITY);
2881
2882 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2883 free(Param);
2884 }
2885
2886 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2887 "Exiting UpnpGetServiceVarStatusAsync\n");
2888
2889 return UPNP_E_SUCCESS;
2890}
2891
2892// Deprecated
2893int UpnpGetServiceVarStatus(UpnpClient_Handle Hnd, const char* ActionURL_const,
2894 const char* VarName_const, DOMString* StVar) {
2895 struct Handle_Info* SInfo = NULL;
2896 int retVal = 0;
2897 char* StVarPtr;
2898 char* ActionURL = (char*)ActionURL_const;
2899 char* VarName = (char*)VarName_const;
2900
2901 if (UpnpSdkInit != 1) {
2902 return UPNP_E_FINISH;
2903 }
2904
2905 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2906 "Inside UpnpGetServiceVarStatus\n");
2907
2909 switch (GetHandleInfo(Hnd, &SInfo)) {
2910 case HND_CLIENT:
2911 break;
2912 default:
2913 HandleUnlock();
2914 return UPNP_E_INVALID_HANDLE;
2915 }
2916
2917 HandleUnlock();
2918
2919 if (ActionURL == NULL) {
2920 return UPNP_E_INVALID_PARAM;
2921 }
2922 if (VarName == NULL || StVar == NULL) {
2923 return UPNP_E_INVALID_PARAM;
2924 }
2925
2926 retVal = SoapGetServiceVarStatus(ActionURL, VarName, &StVarPtr);
2927 *StVar = StVarPtr;
2928
2929 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2930 "Exiting UpnpGetServiceVarStatus \n");
2931
2932 return retVal;
2933}
2934#endif /* COMPA_HAVE_CTRLPT_SOAP */
2935
2936/*******************************************************************************
2937 *
2938 * Client API
2939 *
2940 ******************************************************************************/
2941#ifdef COMPA_HAVE_WEBSERVER
2942int UpnpOpenHttpPost(const char* url, void** handle, const char* contentType,
2943 int contentLength, int timeout) {
2944 int status = http_OpenHttpConnection(url, handle, timeout);
2945 if (status == UPNP_E_SUCCESS) {
2946 return http_MakeHttpRequest(UPNP_HTTPMETHOD_POST, url, handle, NULL,
2947 contentType, contentLength, timeout);
2948 }
2949 return status;
2950}
2951
2952int UpnpWriteHttpPost(void* handle, char* buf, size_t* size, int timeout) {
2953 return http_WriteHttpRequest(handle, buf, size, timeout);
2954}
2955
2956int UpnpCloseHttpPost(void* handle, int* httpStatus, int timeout) {
2957 int status = http_EndHttpRequest(handle, timeout);
2958 if (status == UPNP_E_SUCCESS) {
2959 /* status = */ http_GetHttpResponse(handle, NULL, NULL, NULL,
2960 httpStatus, timeout);
2961 }
2962 status = http_CloseHttpConnection(handle);
2963 return status;
2964}
2965
2966int UpnpOpenHttpGet(const char* url, void** handle, char** contentType,
2967 int* contentLength, int* httpStatus, int timeout) {
2968 int status = UpnpOpenHttpConnection(url, handle, timeout);
2969 if (status == UPNP_E_SUCCESS) {
2970 status = UpnpMakeHttpRequest(UPNP_HTTPMETHOD_GET, url, *handle, NULL,
2971 NULL, 0, timeout);
2972 }
2973 if (status == UPNP_E_SUCCESS) {
2974 status = UpnpEndHttpRequest(*handle, timeout);
2975 }
2976 if (status == UPNP_E_SUCCESS) {
2977 status = UpnpGetHttpResponse(*handle, NULL, contentType, contentLength,
2978 httpStatus, timeout);
2979 }
2980 return status;
2981}
2982
2983int UpnpOpenHttpGetProxy(const char* url, const char* proxy_str, void** handle,
2984 char** contentType, int* contentLength,
2985 int* httpStatus, int timeout) {
2986 int status = UpnpOpenHttpConnection(proxy_str, handle, timeout);
2987 if (status == UPNP_E_SUCCESS) {
2988 status = UpnpMakeHttpRequest(UPNP_HTTPMETHOD_GET, url, *handle, NULL,
2989 NULL, 0, timeout);
2990 }
2991 if (status == UPNP_E_SUCCESS) {
2992 status = UpnpEndHttpRequest(*handle, timeout);
2993 }
2994 if (status == UPNP_E_SUCCESS) {
2995 status = UpnpGetHttpResponse(*handle, NULL, contentType, contentLength,
2996 httpStatus, timeout);
2997 }
2998 return status;
2999}
3000
3001int UpnpOpenHttpGetEx(const char* url_str, void** Handle, char** contentType,
3002 int* contentLength, int* httpStatus, int lowRange,
3003 int highRange, int timeout) {
3004 return http_OpenHttpGetEx(url_str, Handle, contentType, contentLength,
3005 httpStatus, lowRange, highRange, timeout);
3006}
3007
3008int UpnpCancelHttpGet(void* Handle) { return http_CancelHttpGet(Handle); }
3009
3010int UpnpCloseHttpGet(void* Handle) { return UpnpCloseHttpConnection(Handle); }
3011
3012int UpnpReadHttpGet(void* Handle, char* buf, size_t* size, int timeout) {
3013 return http_ReadHttpResponse(Handle, buf, size, timeout);
3014}
3015
3016int UpnpHttpGetProgress(void* Handle, size_t* length, size_t* total) {
3017 return http_HttpGetProgress(Handle, length, total);
3018}
3019
3020int UpnpOpenHttpConnection(const char* url, void** handle, int timeout) {
3021 return http_OpenHttpConnection(url, handle, timeout);
3022}
3023
3024int UpnpMakeHttpRequest(Upnp_HttpMethod method, const char* url, void* handle,
3025 UpnpString* headers, const char* contentType,
3026 int contentLength, int timeout) {
3027 return http_MakeHttpRequest(method, url, handle, headers, contentType,
3028 contentLength, timeout);
3029}
3030
3031int UpnpWriteHttpRequest(void* handle, char* buf, size_t* size, int timeout) {
3032 return http_WriteHttpRequest(handle, buf, size, timeout);
3033}
3034
3035int UpnpEndHttpRequest(void* handle, int timeout) {
3036 return http_EndHttpRequest(handle, timeout);
3037}
3038
3039int UpnpGetHttpResponse(void* handle, UpnpString* headers, char** contentType,
3040 int* contentLength, int* httpStatus, int timeout) {
3041 return http_GetHttpResponse(handle, headers, contentType, contentLength,
3042 httpStatus, timeout);
3043}
3044
3045int UpnpReadHttpResponse(void* handle, char* buf, size_t* size, int timeout) {
3046 return http_ReadHttpResponse(handle, buf, size, timeout);
3047}
3048
3049int UpnpCloseHttpConnection(void* handle) {
3050 return http_CloseHttpConnection(handle);
3051}
3052#endif // COMPA_HAVE_WEBSERVER
3053
3054#ifdef COMPA_HAVE_WEBSERVER
3055int UpnpDownloadUrlItem(const char* url, char** outBuf, char* contentType) {
3056 int ret_code;
3057 size_t doc_length;
3058
3059 if (url == nullptr || outBuf == nullptr || contentType == nullptr)
3060 return UPNP_E_INVALID_PARAM;
3061 ret_code = http_Download(url, HTTP_DEFAULT_TIMEOUT, outBuf, &doc_length,
3062 contentType);
3063 if (ret_code > 0)
3064 /* error reply was received */
3065 ret_code = UPNP_E_INVALID_URL;
3066
3067 return ret_code;
3068}
3069#else
3070int UpnpDownloadUrlItem([[maybe_unused]] const char* url,
3071 [[maybe_unused]] char** outBuf,
3072 [[maybe_unused]] char* contentType) {
3073 return UPNP_E_INVALID_PARAM;
3074}
3075#endif
3076
3077int UpnpDownloadXmlDoc(const char* url, IXML_Document** xmlDoc) {
3078 TRACE("Executing UpnpDownloadXmlDoc()")
3079 if (url == nullptr || xmlDoc == nullptr) {
3080 return UPNP_E_INVALID_PARAM;
3081 }
3082
3083 char* xml_buf;
3084 char content_type[LINE_SIZE];
3085 int ret_code = UpnpDownloadUrlItem(url, &xml_buf, content_type);
3086 if (ret_code != UPNP_E_SUCCESS) {
3087 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3088 "Error downloading document, retCode: %d\n", ret_code);
3089 return ret_code;
3090 }
3091
3092 if (strncasecmp(content_type, "text/xml", strlen("text/xml"))) {
3093 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, "Not text/xml\n");
3094 /* Linksys WRT54G router returns
3095 * "CONTENT-TYPE: application/octet-stream".
3096 * Let's be nice to Linksys and try to parse document anyway.
3097 * If the data sended is not a xml file, ixmlParseBufferEx
3098 * will fail and the function will return UPNP_E_INVALID_DESC
3099 * too. */
3100#if 0
3101 free(xml_buf);
3102 return UPNP_E_INVALID_DESC;
3103#endif
3104 }
3105
3106 ret_code = ixmlParseBufferEx(xml_buf, xmlDoc);
3107 free(xml_buf);
3108 if (ret_code != IXML_SUCCESS) {
3109 if (ret_code == IXML_INSUFFICIENT_MEMORY) {
3110 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3111 "Out of memory, ixml error code: %d\n", ret_code);
3112 return UPNP_E_OUTOF_MEMORY;
3113 } else {
3114 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3115 "Invalid Description, ixml error code: %d\n", ret_code);
3116 return UPNP_E_INVALID_DESC;
3117 }
3118 } else {
3119#ifdef DEBUG
3120 xml_buf = ixmlPrintNode((IXML_Node*)*xmlDoc);
3121 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3122 "Printing the Parsed xml document \n %s\n", xml_buf);
3123 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3124 "****************** END OF Parsed XML Doc "
3125 "*****************\n");
3126 ixmlFreeDOMString(xml_buf);
3127#endif
3128 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3129 "Exiting UpnpDownloadXmlDoc\n");
3130
3131 return UPNP_E_SUCCESS;
3132 }
3133}
3134
3138#if defined(COMPA_HAVE_CTRLPT_SOAP) || defined(COMPA_HAVE_CTRLPT_GENA)
3140 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3141 "Inside UpnpThreadDistribution \n");
3142
3143 switch (Param->FunName) {
3144#ifdef COMPA_HAVE_CTRLPT_GENA
3145 case SUBSCRIBE: {
3147 UpnpString* Sid = UpnpString_new();
3148
3150 int errCode = genaSubscribe(Param->Handle,
3152 (int*)&Param->TimeOut, Sid);
3153 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3156 Param->Fun(UPNP_EVENT_SUBSCRIBE_COMPLETE, evt, Param->Cookie);
3157 UpnpString_delete(Sid);
3159 free(Param);
3160 break;
3161 }
3162 case UNSUBSCRIBE: {
3165 int errCode =
3167 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3170 Param->Fun(UPNP_EVENT_UNSUBSCRIBE_COMPLETE, evt, Param->Cookie);
3172 free(Param);
3173 break;
3174 }
3175 case RENEW: {
3178 int errCode = genaRenewSubscription(
3179 Param->Handle, UpnpEventSubscribe_get_SID(evt), &Param->TimeOut);
3180 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3182 Param->Fun(UPNP_EVENT_RENEWAL_COMPLETE, evt, Param->Cookie);
3184 free(Param);
3185 break;
3186 }
3187#endif /* COMPA_HAVE_CTRLPT_GENA */
3188#ifdef COMPA_HAVE_CTRLPT_SOAP
3189 case ACTION: {
3191 IXML_Document* actionResult = NULL;
3192 int errCode;
3193 if (Param->Header) {
3194 errCode =
3195 SoapSendActionEx(Param->Url, Param->ServiceType, Param->Header,
3196 Param->Act, &actionResult);
3197 } else {
3198 errCode = SoapSendAction(Param->Url, Param->ServiceType, Param->Act,
3199 &actionResult);
3200 }
3201 UpnpActionComplete_set_ErrCode(Evt, errCode);
3203 UpnpActionComplete_set_ActionResult(Evt, actionResult);
3205 Param->Fun(UPNP_CONTROL_ACTION_COMPLETE, Evt, Param->Cookie);
3207 ixmlDocument_free(actionResult);
3208 free_action_arg((job_arg*)Param);
3209 break;
3210 }
3211 case STATUS: {
3213 DOMString currentVal = NULL;
3214 int errCode =
3215 SoapGetServiceVarStatus(Param->Url, Param->VarName, &currentVal);
3219 UpnpStateVarComplete_set_CurrentVal(Evt, currentVal);
3220 Param->Fun(UPNP_CONTROL_GET_VAR_COMPLETE, Evt, Param->Cookie);
3221 free(Param);
3223 break;
3224 }
3225#endif /* COMPA_HAVE_CTRLPT_SOAP */
3226 default:
3227 break;
3228 }
3229
3230 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3231 "Exiting UpnpThreadDistribution\n");
3232}
3233#endif /* COMPA_HAVE_CTRLPT_SOAP || COMPA_HAVE_CTRLPT_GENA */
3234
3241 return ((struct Handle_Info*)HandleTable[Hnd])->Callback;
3242}
3243
3244/* Assumes at most one client */
3246 struct Handle_Info** HndInfo) {
3247 UpnpClient_Handle client;
3248
3249 for (client = 1; client < NUM_HANDLE; client++) {
3250 switch (GetHandleInfo(client, HndInfo)) {
3251 case HND_TABLE_INVALID:
3252 goto exit_loop;
3253 case HND_CLIENT:
3254 *client_handle_out = client;
3255 return HND_CLIENT;
3256 default:;
3257 }
3258 }
3259exit_loop:
3260 *client_handle_out = -1;
3261 return HND_INVALID;
3262}
3263
3266 [[maybe_unused]] int AddressFamily,
3267 UpnpDevice_Handle* device_handle_out,
3268 [[maybe_unused]] struct Handle_Info** HndInfo) {
3269#ifdef COMPA_HAVE_DEVICE_SSDP
3270 /* Check if we've got a registered device of the address family
3271 * specified. */
3272 if ((AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 0) ||
3273 (AddressFamily == AF_INET6 && UpnpSdkDeviceregisteredV6 == 0)) {
3274 *device_handle_out = -1;
3275 return HND_INVALID;
3276 }
3277 if (start < 0 || start >= NUM_HANDLE - 1) {
3278 *device_handle_out = -1;
3279 return HND_INVALID;
3280 }
3281 ++start;
3282 /* Find it. */
3283 for (*device_handle_out = start; *device_handle_out < NUM_HANDLE;
3284 (*device_handle_out)++) {
3285 switch (GetHandleInfo(*device_handle_out, HndInfo)) {
3286 case HND_DEVICE:
3287 if ((*HndInfo)->DeviceAf == AddressFamily) {
3288 return HND_DEVICE;
3289 }
3290 break;
3291 default:
3292 break;
3293 }
3294 }
3295#endif /* COMPA_HAVE_DEVICE_SSDP */
3296
3297 *device_handle_out = -1;
3298 return HND_INVALID;
3299}
3300
3302GetDeviceHandleInfoForPath([[maybe_unused]] const char* path,
3303 [[maybe_unused]] int AddressFamily,
3304 UpnpDevice_Handle* device_handle_out,
3305 [[maybe_unused]] struct Handle_Info** HndInfo,
3306 [[maybe_unused]] service_info** serv_info) {
3307#ifdef COMPA_HAVE_DEVICE_SSDP
3308 /* Check if we've got a registered device of the address family
3309 * specified. */
3310 if ((AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 0) ||
3311 (AddressFamily == AF_INET6 && UpnpSdkDeviceregisteredV6 == 0)) {
3312 *device_handle_out = -1;
3313 return HND_INVALID;
3314 }
3315 /* Find it. */
3316 for (*device_handle_out = 1; *device_handle_out < NUM_HANDLE;
3317 (*device_handle_out)++) {
3318 switch (GetHandleInfo(*device_handle_out, HndInfo)) {
3319 case HND_DEVICE:
3320 if ((*HndInfo)->DeviceAf == AddressFamily) {
3321 if (((*serv_info = FindServiceControlURLPath(
3322 &(*HndInfo)->ServiceTable, path)) != 0) ||
3323 ((*serv_info = FindServiceEventURLPath(
3324 &(*HndInfo)->ServiceTable, path)) != 0)) {
3325 return HND_DEVICE;
3326 }
3327 }
3328 break;
3329 default:
3330 break;
3331 }
3332 }
3333#endif /* COMPA_HAVE_DEVICE_SSDP */
3334
3335 *device_handle_out = -1;
3336 return HND_INVALID;
3337}
3338
3340 // This function expects an initialized global HandleTable HndInfo,
3341 // at least with nullptr.
3342 Upnp_Handle_Type ret{HND_TABLE_INVALID};
3343
3344 if (HndInfo == nullptr) {
3345 UPnPsdk_LOGERR("MSG1097") "No output variable for handle info "
3346 "available (HndInfo==nullptr).\n";
3347 } else if (Hnd < 1 || Hnd >= NUM_HANDLE) {
3348 UPnPsdk_LOGERR("MSG1130") "Handle(" << Hnd << ") out of range.\n";
3349 ret = HND_INVALID;
3350 } else if (HandleTable[Hnd] == nullptr) {
3351 // When scanning the whole handle info table we have a lot of empty
3352 // entries. That seems not to be an error.
3353 ret = HND_INVALID;
3354 } else {
3355 *HndInfo = HandleTable[Hnd];
3356 ret = (*HndInfo)->HType;
3357 }
3358 return ret;
3359}
3360
3362 struct Handle_Info* HndInfo;
3363 if (HandleTable[Hnd] != nullptr) {
3364 HndInfo = HandleTable[Hnd];
3365 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3366 "Printing information for Handle_%d\n", Hnd);
3367 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "HType_%d\n",
3368 HndInfo->HType);
3369#ifdef COMPA_HAVE_DEVICE_SSDP
3370 switch (HndInfo->HType) {
3371 case HND_CLIENT:
3372 break;
3373 default:
3374 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "DescURL_%s\n",
3375 HndInfo->DescURL);
3376 }
3377#endif
3378 } else {
3379 return UPNP_E_INVALID_HANDLE;
3380 }
3381
3382 return UPNP_E_SUCCESS;
3383}
3384
3385#ifdef COMPA_HAVE_DEVICE_SSDP
3386void AutoAdvertise(void* input) {
3387 job_arg* arg = (job_arg*)input;
3388
3389 UpnpSendAdvertisement(arg->advertise.handle, *((int*)arg->advertise.Event));
3390 free_advertise_arg(arg);
3391}
3392#endif
3393
3394#ifdef COMPA_HAVE_WEBSERVER
3395int UpnpSetWebServerRootDir(const char* rootDir) {
3396 TRACE("Executing UpnpSetWebServerRootDir()")
3397 if (UpnpSdkInit == 0)
3398 return UPNP_E_FINISH;
3399 if ((rootDir == nullptr) || (strlen(rootDir) == 0)) {
3400 return UPNP_E_INVALID_PARAM;
3401 }
3402
3404
3405 return web_server_set_root_dir(rootDir);
3406}
3407#endif // COMPA_HAVE_WEBSERVER
3408
3409#ifdef COMPA_HAVE_WEBSERVER
3410int UpnpSetWebServerCorsString(const char* corsString) {
3411 if (UpnpSdkInit == 0)
3412 return UPNP_E_FINISH;
3413 if ((corsString == NULL) || (strlen(corsString) == 0)) {
3414 return UPNP_E_INVALID_PARAM;
3415 }
3416
3418
3419 return web_server_set_cors(corsString);
3420}
3421#endif /* COMPA_HAVE_WEBSERVER */
3422
3423int UpnpAddVirtualDir(const char* newDirName, const void* cookie,
3424 const void** oldcookie) {
3425 virtualDirList* pNewVirtualDir;
3426 virtualDirList* pLast;
3427 virtualDirList* pCurVirtualDir;
3428 char dirName[NAME_SIZE];
3429
3430 memset(dirName, 0, sizeof(dirName));
3431 if (UpnpSdkInit != 1) {
3432 /* SDK is not initialized */
3433 return UPNP_E_FINISH;
3434 }
3435
3436 if ((newDirName == NULL) || (strlen(newDirName) == (size_t)0)) {
3437 return UPNP_E_INVALID_PARAM;
3438 }
3439
3440 if (*newDirName != '/') {
3441 if (strlen(newDirName) > sizeof(dirName) - 2)
3442 return UPNP_E_INVALID_PARAM;
3443 dirName[0] = '/';
3444 strncpy(dirName + 1, newDirName, sizeof(dirName) - 2);
3445 } else {
3446 if (strlen(newDirName) > sizeof(dirName) - 1)
3447 return UPNP_E_INVALID_PARAM;
3448 strncpy(dirName, newDirName, sizeof(dirName) - 1);
3449 }
3450
3451 pCurVirtualDir = pVirtualDirList;
3452 while (pCurVirtualDir != NULL) {
3453 /* already has this entry */
3454 if (strcmp(pCurVirtualDir->dirName, dirName) == 0) {
3455 if (oldcookie != NULL)
3456 *oldcookie = pCurVirtualDir->cookie;
3457 pCurVirtualDir->cookie = cookie;
3458 return UPNP_E_SUCCESS;
3459 }
3460
3461 pCurVirtualDir = pCurVirtualDir->next;
3462 }
3463
3464 pNewVirtualDir = (virtualDirList*)malloc(sizeof(virtualDirList));
3465 if (pNewVirtualDir == NULL) {
3466 return UPNP_E_OUTOF_MEMORY;
3467 }
3468 pNewVirtualDir->next = NULL;
3469 if (oldcookie != NULL)
3470 *oldcookie = NULL;
3471 pNewVirtualDir->cookie = cookie;
3472 memset(pNewVirtualDir->dirName, 0, sizeof(pNewVirtualDir->dirName));
3473#ifdef UPNPLIB_PUPNP_BUG
3474 // Error if compiling old code with build type Release: output may be
3475 // truncated copying 255 bytes from a string of length 255
3476 // [-Werror=stringop-truncation]. We have to fix it here otherwise it won't
3477 // compile. --Ingo
3478 strncpy(pNewVirtualDir->dirName, dirName,
3479 sizeof(pNewVirtualDir->dirName) - 1);
3480#else
3481 strncpy(pNewVirtualDir->dirName, dirName, sizeof(pNewVirtualDir->dirName));
3482#endif
3483 *(pNewVirtualDir->dirName + strlen(dirName)) = 0;
3484
3485 if (pVirtualDirList == NULL) { /* first virtual dir */
3486 pVirtualDirList = pNewVirtualDir;
3487 } else {
3488 pLast = pVirtualDirList;
3489 while (pLast->next != NULL) {
3490 pLast = pLast->next;
3491 }
3492 pLast->next = pNewVirtualDir;
3493 }
3494
3495 return UPNP_E_SUCCESS;
3496}
3497
3498int UpnpRemoveVirtualDir(const char* dirName) {
3499 virtualDirList* pPrev;
3500 virtualDirList* pCur;
3501 int found = 0;
3502
3503 if (UpnpSdkInit != 1) {
3504 return UPNP_E_FINISH;
3505 }
3506
3507 if (dirName == NULL) {
3508 return UPNP_E_INVALID_PARAM;
3509 }
3510
3511 if (pVirtualDirList == NULL) {
3512 return UPNP_E_INVALID_PARAM;
3513 }
3514 /* Handle the special case where the directory that we are */
3515 /* removing is the first in the list. */
3516 if (strcmp(pVirtualDirList->dirName, dirName) == 0) {
3517 pPrev = pVirtualDirList;
3519 free(pPrev);
3520 return UPNP_E_SUCCESS;
3521 }
3522
3523 pCur = pVirtualDirList->next;
3524 pPrev = pVirtualDirList;
3525
3526 while (pCur != NULL) {
3527 if (strcmp(pCur->dirName, dirName) == 0) {
3528 pPrev->next = pCur->next;
3529 free(pCur);
3530 found = 1;
3531 break;
3532 } else {
3533 pPrev = pCur;
3534 pCur = pCur->next;
3535 }
3536 }
3537
3538 if (found == 1)
3539 return UPNP_E_SUCCESS;
3540 else
3541 return UPNP_E_INVALID_PARAM;
3542}
3543
3545 virtualDirList* pCur;
3546 virtualDirList* pNext;
3547
3548 if (UpnpSdkInit != 1) {
3549 return;
3550 }
3551
3552 pCur = pVirtualDirList;
3553
3554 while (pCur != NULL) {
3555 pNext = pCur->next;
3556 free(pCur);
3557
3558 pCur = pNext;
3559 }
3560
3561 pVirtualDirList = NULL;
3562}
3563
3564int UpnpEnableWebserver([[maybe_unused]] int enable) {
3565 TRACE("Executing UpnpEnableWebserver()")
3566 if (UpnpSdkInit != 1) {
3567 return UPNP_E_FINISH;
3568 }
3569#ifdef COMPA_HAVE_WEBSERVER
3570 if (enable)
3572 else
3574 return UPNP_E_SUCCESS;
3575#else /* Internal web server disabled */
3576 return UPNP_E_NO_WEB_SERVER;
3577#endif /* COMPA_HAVE_WEBSERVER */
3578}
3579
3581 if (UpnpSdkInit != 1) {
3582 return 0;
3583 }
3584 return bWebServerState == (WebServerState)WEB_SERVER_ENABLED;
3585}
3586
3588 void* cookie) {
3589 gWebCallback_HostValidate = callback;
3591}
3592
3596
3598 if (!callback) {
3599 return UPNP_E_INVALID_PARAM;
3600 } else {
3601 virtualDirCallback.get_info = callback;
3602 return UPNP_E_SUCCESS;
3603 }
3604}
3605
3607 if (!callback) {
3608 return UPNP_E_INVALID_PARAM;
3609 } else {
3610 virtualDirCallback.open = callback;
3611 return UPNP_E_SUCCESS;
3612 }
3613}
3614
3616 if (!callback) {
3617 return UPNP_E_INVALID_PARAM;
3618 } else {
3619 virtualDirCallback.read = callback;
3620 return UPNP_E_SUCCESS;
3621 }
3622}
3623
3625 if (!callback) {
3626 return UPNP_E_INVALID_PARAM;
3627 } else {
3628 virtualDirCallback.write = callback;
3629 return UPNP_E_SUCCESS;
3630 }
3631}
3632
3634 if (!callback) {
3635 return UPNP_E_INVALID_PARAM;
3636 } else {
3637 virtualDirCallback.seek = callback;
3638 return UPNP_E_SUCCESS;
3639 }
3640}
3641
3643 if (!callback) {
3644 return UPNP_E_INVALID_PARAM;
3645 } else {
3646 virtualDirCallback.close = callback;
3647 return UPNP_E_SUCCESS;
3648 }
3649}
3650
3651int UpnpSetMaxContentLength(size_t contentLength) {
3652 int errCode = UPNP_E_SUCCESS;
3653
3654 do {
3655 if (UpnpSdkInit != 1) {
3656 errCode = UPNP_E_FINISH;
3657 break;
3658 }
3659 g_maxContentLength = contentLength;
3660 } while (0);
3661
3662 return errCode;
3663}
@ UPNP_EVENT_RENEWAL_COMPLETE
Definition Callback.hpp:93
@ UPNP_CONTROL_ACTION_COMPLETE
Definition Callback.hpp:33
@ UPNP_EVENT_SUBSCRIBE_COMPLETE
Definition Callback.hpp:98
@ UPNP_CONTROL_GET_VAR_COMPLETE
Definition Callback.hpp:44
@ UPNP_EVENT_UNSUBSCRIBE_COMPLETE
Definition Callback.hpp:103
int(* Upnp_FunPtr)(Upnp_EventType EventType, const void *Event, void *Cookie)
Definition Callback.hpp:143
char Upnp_SID[44]
Holds the subscription identifier for a subscription between a client and a device.
Definition API.hpp:431
#define UPNP_E_NO_WEB_SERVER
The operation completed successfully.
Definition API.hpp:354
Upnp_DescType_e
Specifies the type of description in UpnpRegisterRootDevice2.
Definition API.hpp:465
@ UPNPREG_FILENAME_DESC
Definition API.hpp:471
@ UPNPREG_BUF_DESC
Definition API.hpp:475
@ UPNPREG_URL_DESC
Definition API.hpp:467
#define NAME_SIZE
Definition API.hpp:46
int UpnpClient_Handle
Returned when a control point application registers with UpnpRegisterClient().
Definition API.hpp:412
#define UPNP_INFINITE
Definition API.hpp:51
int UpnpDevice_Handle
Returned when a device application registers with UpnpRegisterRootDevice(),UpnpRegisterRootDevice2(),...
Definition API.hpp:422
#define LINE_SIZE
Definition API.hpp:45
enum Upnp_DescType_e Upnp_DescType
Represents the different types of searches that can be performed using the SDK for UPnP Devices API.
Definition API.hpp:478
int web_server_set_root_dir(const char *root_dir)
Assign the path to the global Document root directory.
int web_server_set_cors(const char *cors_string)
Assign the Access-Control-Allow-Origin specfied by the input const char* cors_string parameterto the ...
int web_server_set_alias(const char *a_alias_name, const char *a_alias_content, size_t a_alias_content_length, time_t a_last_modified)
Replaces current alias with the given alias.
void web_server_destroy()
Release memory allocated for the global web server root directory and the global XML document.
void web_server_init()
Initilialize root directory for web server and different documents.
membuffer gDocumentRootDir
Definition webserver.hpp:44
int ListDestroy(LinkedList *list, int freeItem)
Removes all memory associated with list nodes. Does not free LinkedList *list.
void * ListDelNode(LinkedList *list, ListNode *dnode, int freeItem)
Removes a node from the list. The memory for the node is freed.
ListNode * ListHead(LinkedList *list)
Returns the head of the list.
int ListInit(LinkedList *list, cmp_routine cmp_func, free_function free_func)
Initializes LinkedList. Must be called first and only once for List.
Linked list node. Stores generic item and pointers to next and prev.
int ThreadPoolInit(ThreadPool *tp, ThreadPoolAttr *attr)
Initializes and starts ThreadPool.
int ThreadPoolAdd(ThreadPool *tp, ThreadPoolJob *job, int *jobId)
Adds a job to the thread pool.
int TPJobSetFreeFunction(ThreadPoolJob *job, free_routine func)
Sets the jobs free function.
int ThreadPoolShutdown(ThreadPool *tp)
Shuts the thread pool down.
int TPAttrSetMaxJobsTotal(ThreadPoolAttr *attr, int totalMaxJobs)
Sets the maximum number jobs that can be qeued totally.
int TPAttrSetMaxThreads(ThreadPoolAttr *attr, int maxThreads)
Sets the max threads for the thread pool attributes.
int TPJobSetPriority(ThreadPoolJob *job, ThreadPriority priority)
Sets the priority of the threadpool job.
int ThreadPoolGetStats(ThreadPool *tp, ThreadPoolStats *stats)
Returns various statistics about the thread pool.
int TPAttrSetJobsPerThread(ThreadPoolAttr *attr, int jobsPerThread)
Sets the jobs per thread ratio.
int TPJobInit(ThreadPoolJob *job, UPnPsdk::start_routine func, void *arg)
Initializes thread pool job.
int TPAttrInit(ThreadPoolAttr *attr)
Initializes thread pool attributes.
int TPAttrSetIdleTime(ThreadPoolAttr *attr, int idleTime)
Sets the idle time for the thread pool attributes.
int TPAttrSetMinThreads(ThreadPoolAttr *attr, int minThreads)
Sets the min threads for the thread pool attributes.
int maxJobsTotal
int TPAttrSetStackSize(ThreadPoolAttr *attr, size_t stackSize)
Sets the stack size for the thread pool attributes.
void(* free_routine)(void *arg)
A thread pool.
Internal ThreadPool Job.
Structure to hold statistics.
Attributes for thread pool.
int TimerThreadShutdown(TimerThread *timer)
Shutdown the timer thread.
int TimerThreadInit(TimerThread *timer, ThreadPool *tp)
Initializes and starts timer thread.
int TimerThreadSchedule(TimerThread *timer, time_t timeout, TimeoutType type, ThreadPoolJob *job, Duration duration, int *id)
Schedules an event to run at a specified time.
@ REL_SEC
seconds from current time.
A timer thread that allows the scheduling of a job to run at a specified time in the future.
UpnpActionComplete.
PUPNP_Api int UpnpActionComplete_strcpy_CtrlUrl(UpnpActionComplete *p, const char *s)
PUPNP_Api UpnpActionComplete * UpnpActionComplete_new(void)
PUPNP_Api int UpnpActionComplete_set_ErrCode(UpnpActionComplete *p, int n)
PUPNP_Api void UpnpActionComplete_delete(UpnpActionComplete *p)
PUPNP_Api int UpnpActionComplete_set_ActionRequest(UpnpActionComplete *p, IXML_Document *n)
PUPNP_Api int UpnpActionComplete_set_ActionResult(UpnpActionComplete *p, IXML_Document *n)
s_UpnpEventSubscribe
PUPNP_Api int UpnpEventSubscribe_set_ErrCode(UpnpEventSubscribe *p, int n)
PUPNP_Api const UpnpString * UpnpEventSubscribe_get_PublisherUrl(const UpnpEventSubscribe *p)
PUPNP_Api UpnpEventSubscribe * UpnpEventSubscribe_new(void)
PUPNP_Api int UpnpEventSubscribe_set_SID(UpnpEventSubscribe *p, const UpnpString *s)
PUPNP_Api const UpnpString * UpnpEventSubscribe_get_SID(const UpnpEventSubscribe *p)
PUPNP_Api int UpnpEventSubscribe_strcpy_SID(UpnpEventSubscribe *p, const char *s)
PUPNP_Api int UpnpEventSubscribe_set_TimeOut(UpnpEventSubscribe *p, int n)
PUPNP_Api int UpnpEventSubscribe_strcpy_PublisherUrl(UpnpEventSubscribe *p, const char *s)
PUPNP_Api void UpnpEventSubscribe_delete(UpnpEventSubscribe *p)
s_UpnpStateVarComplete
PUPNP_Api UpnpStateVarComplete * UpnpStateVarComplete_new(void)
PUPNP_Api void UpnpStateVarComplete_delete(UpnpStateVarComplete *p)
PUPNP_Api int UpnpStateVarComplete_set_CurrentVal(UpnpStateVarComplete *p, const DOMString s)
PUPNP_Api int UpnpStateVarComplete_set_ErrCode(UpnpStateVarComplete *p, int n)
PUPNP_Api int UpnpStateVarComplete_strcpy_CtrlUrl(UpnpStateVarComplete *p, const char *s)
PUPNP_Api int UpnpStateVarComplete_strcpy_StateVarName(UpnpStateVarComplete *p, const char *s)
VDCallback_Read read
char dirName[NAME_SIZE]
VDCallback_Open open
VDCallback_Close close
VDCallback_Write write
const void * cookie
VDCallback_GetInfo get_info
struct virtual_Dir_List * next
VDCallback_Seek seek
Virtual directory list.
Declaration of the Addrinfo class.
Get information from local network adapters.
UPnPsdk_API void get_first()
Load a list of network adapters from the operating system and select its first entry.
UPnPsdk_API void sockaddr(SSockaddr &a_saddr) const
Get socket address from current selected list entry.
UPnPsdk_API bool find_next()
Find next ip address from local network adapters.
UPnPsdk_API unsigned int index() const
Get index number from current selected list entry.
UPnPsdk_API std::string name() const
Get network adapter name from current selected list entry.
UPnPsdk_API bool find_first(std::string_view a_name_or_addr="")
Find local network adapter with given name or ip address.
UPnPsdk_API unsigned int bitmask() const
Get prefix length from the ip address of the current selected local network adapter.
#define MIN_THREADS
The MIN_THREADS constant defines the minimum number of threads the thread pool inside the SDK will cr...
Definition config.hpp:77
#define MAX_SUBSCRIPTION_QUEUED_EVENTS
The MAX_SUBSCRIPTION_QUEUED_EVENTS determines the maximum number of events which can be queued for a ...
Definition config.hpp:115
#define MAX_SUBSCRIPTION_EVENT_AGE
The MAX_SUBSCRIPTION__EVENT_AGE determines the maximum number of seconds which an event can spend on ...
Definition config.hpp:127
#define DEFAULT_SOAP_CONTENT_LENGTH
SOAP messages will read at most DEFAULT_SOAP_CONTENT_LENGTH bytes. This prevents devices that have a ...
Definition config.hpp:135
#define MAX_THREADS
The MAX_THREADS constant defines the maximum number of threads the thread pool inside the SDK will cr...
Definition config.hpp:88
#define THREAD_STACK_SIZE
The THREAD_STACK_SIZE constant defines the minimum stack size (in bytes) allocated for the stack of e...
Definition config.hpp:100
#define THREAD_IDLE_TIME
The THREAD_IDLE_TIME constant determines when a thread will be removed from the thread pool and retur...
Definition config.hpp:58
#define AUTO_ADVERTISEMENT_TIME
The AUTO_ADVERTISEMENT_TIME is the time, in seconds, before an device advertisements expires before a...
Definition config.hpp:204
#define JOBS_PER_THREAD
The JOBS_PER_THREAD constant determines when a new thread will be allocated to the thread pool inside...
Definition config.hpp:67
Manage Eventing with GENA, the General Event Notification Architecture.
void genaCallback(http_parser_t *parser, http_message_t *request, SOCKINFO *info)
This is the callback function called by the miniserver to handle incoming GENA requests.
int clientSubscribeMutexInit()
Initialize the client subsribe mutex.
int genaUnregisterClient(UpnpClient_Handle client_handle)
Unsubcribes all the outstanding subscriptions and cleans the subscription list.
struct UpnpNonblockParam action
UpnpNonblockParam.
Definition upnpapi.cpp:224
int genaUnSubscribe(UpnpClient_Handle client_handle, const UpnpString *in_sid)
Unsubscribes a SID.
struct job_arg::@0 advertise
advertise
int genaSubscribe(UpnpClient_Handle client_handle, const UpnpString *PublisherURL, int *TimeOut, UpnpString *out_sid)
This function subscribes to a PublisherURL (also mentioned as EventURL in some places).
int clientSubscribeMutexDestroy()
Destroy the client subsribe mutex.
int genaRenewSubscription(UpnpClient_Handle client_handle, const UpnpString *in_sid, int *TimeOut)
Renews a SID.
job_arg
Definition upnpapi.cpp:216
int genaNotifyAll(UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count)
Sends a notification to all the subscribed control points.
int genaUnregisterDevice(UpnpDevice_Handle device_handle)
Cleans the service table of the device.
int genaNotifyAllExt(UpnpDevice_Handle device_handle, char *UDN, char *servId, IXML_Document *PropSet)
Sends a notification to all the subscribed control points.
int genaInitNotifyExt(UpnpDevice_Handle device_handle, char *UDN, char *servId, IXML_Document *PropSet, const Upnp_SID sid)
Similar to the genaInitNofity. The only difference is that it takes the xml document for the state ta...
int genaInitNotify(UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count, const Upnp_SID sid)
Sends the intial state table dump to newly subscribed control point.
int SearchByTarget(int Hnd, int Mx, char *St, void *Cookie)
Creates and send the search request for a specific URL.
int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd, enum SsdpSearchType SearchType, struct sockaddr *DestAddr, char *DeviceType, char *DeviceUDN, char *ServiceType, int Exp)
Sends SSDP advertisements, replies and shutdown messages.
Internal implementation of the class UpnpString.
PUPNP_Api int UpnpString_set_String(UpnpString *p, const char *s)
Sets the string from a pointer to char.
PUPNP_Api UpnpString * UpnpString_new(void)
Constructor.
PUPNP_Api const char * UpnpString_get_String(const UpnpString *p)
Returns the pointer to char.
PUPNP_Api void UpnpString_delete(UpnpString *p)
Destructor.
Data structure common to all types of nodes.
Definition ixml.hpp:132
Data structure representing the DOM Document.
Definition ixml.hpp:155
PUPNP_Api DOMString ixmlPrintNode(IXML_Node *doc)
Renders a Node and all sub-elements into an XML text representation.
Definition ixml.cpp:344
PUPNP_Api int ixmlParseBufferEx(const char *buffer, IXML_Document **doc)
Parses an XML text buffer converting it into an IXML DOM representation.
Definition ixml.cpp:396
#define DOMString
The type of DOM strings.
Definition ixml.hpp:47
PUPNP_Api IXML_NodeList * ixmlDocument_getElementsByTagName(IXML_Document *doc, const DOMString tagName)
Returns a NodeList of all Elements that match the given tag name in the order in which they were enco...
Definition document.cpp:449
PUPNP_Api void ixmlFreeDOMString(DOMString buf)
Frees a DOMString.
Definition ixml.cpp:423
PUPNP_Api void ixmlNodeList_free(IXML_NodeList *nList)
Frees a NodeList object.
Definition nodeList.cpp:129
PUPNP_Api void ixmlDocument_free(IXML_Document *doc)
Frees a Document object and all Nodes associated with it.
Definition document.cpp:49
PUPNP_Api int UpnpRegisterClient(Upnp_FunPtr Fun, const void *Cookie, UpnpClient_Handle *Hnd)
Registers a control point application with the UPnP Library.
PUPNP_Api int UpnpRegisterRootDevice3(const char *const DescUrl, const Upnp_FunPtr Fun, const void *const Cookie, UpnpDevice_Handle *const Hnd, const int AddressFamily)
Registers one UPnP device object for a specific address family with the UPnP library and get a handle...
Definition upnpapi.cpp:1308
PUPNP_Api int UpnpUnRegisterClient(UpnpClient_Handle Hnd)
Unregisters a control point application, unsubscribing all active subscriptions.
int UpnpInit2(const char *IfName, unsigned short DestPort)
Initializes the Linux SDK for UPnP Devices.
Definition upnpapi.cpp:786
int UpnpGetServiceVarStatus(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *VarName_const, DOMString *StVar)
Queries the state of a state variable of a service on another device.
Definition upnpapi.cpp:2893
Upnp_HttpMethod
Different HTTP methods.
Definition API.hpp:1927
PUPNP_Api int UpnpDownloadXmlDoc(const char *url, IXML_Document **xmlDoc)
Downloads an XML document specified in a URL.
Definition upnpapi.cpp:3077
@ UPNP_HTTPMETHOD_GET
GET.
Definition API.hpp:1930
@ UPNP_HTTPMETHOD_POST
POST.
Definition API.hpp:1932
int UpnpSearchAsync(UpnpClient_Handle Hnd, int Mx, const char *Target_const, const void *Cookie_const)
Searches for devices matching the given search target.
Definition upnpapi.cpp:1820
int UpnpAcceptSubscription(UpnpDevice_Handle Hnd, const char *DevID_const, const char *ServName_const, const char **VarName_const, const char **NewVal_const, int cVariables, const Upnp_SID SubsId)
Accepts a subscription request and sends out the current state of the eventable variables for a servi...
Definition upnpapi.cpp:2382
int(* VDCallback_Close)(UpnpWebFileHandle fileHnd, const void *cookie, const void *request_cookie)
Close callback function prototype.
Definition API.hpp:2728
int(* VDCallback_GetInfo)(const char *filename, UpnpFileInfo *info, const void *cookie, const void **request_cookie)
Get-info callback function prototype.
Definition API.hpp:2574
int(* WebCallback_HostValidate)(const char *hostname, void *cookie)
Callback for validating HTTP requests HOST header values.
Definition API.hpp:2782
int(* VDCallback_Seek)(UpnpWebFileHandle fileHnd, off_t offset, int origin, const void *cookie, const void *request_cookie)
Seek callback function prototype.
Definition API.hpp:2697
int(* VDCallback_Write)(UpnpWebFileHandle fileHnd, char *buf, size_t buflen, const void *cookie, const void *request_cookie)
Write callback function prototype.
Definition API.hpp:2671
int(* VDCallback_Read)(UpnpWebFileHandle fileHnd, char *buf, size_t buflen, const void *cookie, const void *request_cookie)
Read callback function prototype.
Definition API.hpp:2645
UpnpWebFileHandle(* VDCallback_Open)(const char *filename, enum UpnpOpenFileMode Mode, const void *cookie, const void *request_cookie)
Open callback function prototype.
Definition API.hpp:2620
int http_ReadHttpResponse(void *Handle, char *buf, size_t *size, int timeout)
Reads the content of a response using a connection previously created by UpnpOpenHttpConnection().
int http_OpenHttpConnection(const char *url_str, void **Handle, int timeout)
Opens a connection to the server.
int http_CloseHttpConnection(void *Handle)
Closes the connection created with UpnpOpenHttpConnection() and frees any memory associated with the ...
int http_Download(const char *url_str, int timeout_secs, char **document, size_t *doc_length, char *content_type)
Download the document message and extract the document from the message.
int http_CancelHttpGet(void *Handle)
Set the cancel flag of the HttpGet handle.
int http_WriteHttpRequest(void *Handle, char *buf, size_t *size, int timeout)
Writes the content of a HTTP request initiated by a UpnpMakeHttpRequest() call. The end of the conten...
int http_EndHttpRequest(void *Handle, int timeout)
Indicates the end of a HTTP request previously made by UpnpMakeHttpRequest().
int http_OpenHttpGetEx(const char *url_str, void **Handle, char **contentType, int *contentLength, int *httpStatus, int lowRange, int highRange, int timeout)
Makes the HTTP GET message, connects to the peer, sends the HTTP GET request, gets the response and p...
int http_GetHttpResponse(void *Handle, UpnpString *headers, char **contentType, int *contentLength, int *httpStatus, int timeout)
Gets the response from the server using a connection previously created by UpnpOpenHttpConnection().
int http_MakeHttpRequest(Upnp_HttpMethod method, const char *url_str, void *Handle, UpnpString *headers, const char *contentType, int contentLength, int timeout)
Makes a HTTP request using a connection previously created by UpnpOpenHttpConnection().
int http_HttpGetProgress(void *Handle, size_t *length, size_t *total)
Extracts information from the Handle to the HTTP get object.
Performs HTTP read and write messages.
#define HTTP_DEFAULT_TIMEOUT
void membuffer_destroy(membuffer *m)
Free's memory allocated for membuffer* m.
Maintains a block of dynamically allocated memory.
Definition membuffer.hpp:61
#define UPNP_E_OUTOF_HANDLE
The SDK does not have any more space for additional handles.
Definition messages.hpp:47
#define UPNP_E_ALREADY_REGISTERED
A client or a device is already registered.
Definition messages.hpp:154
#define UPNP_E_INVALID_HANDLE
The handle passed to a function is not a recognized as a valid handle.
Definition messages.hpp:32
#define UPNP_E_FILE_READ_ERROR
An error happened while reading a file.
Definition messages.hpp:298
#define UPNP_E_INVALID_INTERFACE
The interface provided to UpnpInit2 is unknown or does not have a valid IPv4 or IPv6 address configur...
Definition messages.hpp:160
#define UPNP_E_FILE_NOT_FOUND
The filename passed to one of the device registration functions was not found or was not accessible.
Definition messages.hpp:293
#define UPNP_E_SUCCESS
The operation completed successfully.
Definition messages.hpp:27
#define UPNP_E_OUTOF_MEMORY
Not enough resources are currently available to complete the operation.
Definition messages.hpp:57
#define UPNP_E_INVALID_URL
An URL passed into the function is invalid.
Definition messages.hpp:83
#define UPNP_E_INVALID_ACTION
The SOAP action message is invalid.
Definition messages.hpp:113
#define UPNP_E_FINISH
UpnpInit2 has not been called, or UpnpFinish has already been called.
Definition messages.hpp:121
#define UPNP_E_INIT_FAILED
UpnpInit2 cannot complete.
Definition messages.hpp:128
#define UPNP_E_INVALID_DESC
The description document passed to UpnpRegisterRootDevice, UpnpRegisterRootDevice2 UpnpRegisterRootDe...
Definition messages.hpp:74
#define UPNP_E_INVALID_PARAM
One or more of the parameters passed to the function is not valid.
Definition messages.hpp:40
#define UPNP_E_URL_TOO_BIG
The URL passed into a function is too long.
Definition messages.hpp:135
#define UPNP_E_INIT
The SDK has already been initialized.
Definition messages.hpp:65
#define UPNP_E_EXT_NOT_XML
The file name of the description document passed to UpnpRegisterRootDevice2 does not end in "....
Definition messages.hpp:304
void SetSoapCallback(MiniServerCallback callback)
Set SOAP Callback.
int StartMiniServer(in_port_t *listen_port4, in_port_t *listen_port6, in_port_t *listen_port6UlaGua)
Initialize the sockets functionality for the Miniserver.
int StopMiniServer()
Stop and Shutdown the MiniServer and free socket resources.
void SetGenaCallback(MiniServerCallback callback)
Set GENA Callback.
Manage "Step 0: Addressing" of the UPnP+™ specification.
int FreeHandle(int Upnp_Handle)
Free handle.
Definition upnpapi.cpp:397
int GetFreeHandle()
Get a free UPnP Unit handle.
Definition upnpapi.cpp:376
int UpnpGetIfInfo(const std::string &a_iface="")
Retrieve local network adapter information and keep it in global variables.
Definition upnpapi.cpp:257
Handle_Info * HandleTable[NUM_HANDLE]
UPnP Device and Control Point handle table
Definition upnpapi.cpp:365
pthread_mutex_t sdkInit_mutex
Initialization mutex.
Definition upnpapi.cpp:431
Refactored pupnp program code that is compatible to the original pupnp code.
Manage information about network adapters.
service_info * FindServiceControlURLPath(service_table *table, const char *controlURLPath)
Traverses the service table and finds the node whose control URL Path matches a known value.
void printServiceTable(service_table *table, Upnp_LogLevel level, Dbg_Module module)
Prints the URL base of the table and information of each service from the service table.
service_info * FindServiceEventURLPath(service_table *table, const char *eventURLPath)
Traverses the service table and finds the node whose event URL Path matches a known value.
int getServiceTable(IXML_Node *node, service_table *out, const char *DefaultURLBase)
Retrieve service from the table.
-brief Service information
SOAP declarations for Control Points using SOAP.
int SoapSendActionEx(char *action_url, char *service_type, IXML_Document *header, IXML_Document *action_node, IXML_Document **response_node)
This extended function is called by UPnP API to send the SOAP action request.
int SoapGetServiceVarStatus(char *action_url, DOMString var_name, DOMString *var_value)
This function creates a status variable query message send it to the specified URL....
int SoapSendAction(char *action_url, char *service_type, IXML_Document *action_node, IXML_Document **response_node)
This function is called by UPnP API to send the SOAP action request.
SOAP declarations for UPnP Devices using SOAP.
void soap_device_callback(http_parser_t *parser, http_message_t *request, SOCKINFO *info)
This is a callback called by minisever.
void freeSslCtx()
Free the OpenSSL context.
Definition sock.cpp:610
SsdpSearchType
Enumeration to define all different types of ssdp searches.
Manage "Step 1: Discovery" of the UPnP+™ specification for Control Points with SSDP.
char * searchTarget
part of search argument
SSDP search argument.
Manage "Step 1: Discovery" of the UPnP+™ specification for UPnP Devices with SSDP.
Trivial ::sockaddr structures enhanced with methods.
Definition sockaddr.hpp:133
sockaddr_in6 & sin6
Reference to sockaddr_in6 struct.
Definition sockaddr.hpp:139
bool is_loopback() const
Get if the socket address is a loopback address.
Definition sockaddr.cpp:536
const std::string netaddr() noexcept
Get the assosiated netaddress without port.
Definition sockaddr.cpp:433
sockaddr_storage & ss
Reference to sockaddr_storage struct.
Definition sockaddr.hpp:135
int UpnpSendActionAsync(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *ServiceType_const, const char *DevUDN_const, IXML_Document *Act, Upnp_FunPtr Fun, const void *Cookie_const)
Sends a message to change a state variable in a service, generating a callback when the operation is ...
Definition upnpapi.cpp:2631
WebCallback_HostValidate gWebCallback_HostValidate
webCallback for HOST validation.
Definition upnpapi.cpp:123
Upnp_FunPtr GetCallBackFn(UpnpClient_Handle Hnd)
Get callback function ptr from a handle.
Definition upnpapi.cpp:3240
int UpnpCloseHttpGet(void *Handle)
Closes the connection and frees memory that was allocated for the handle parameter.
Definition upnpapi.cpp:3010
int UpnpSubscribe(UpnpClient_Handle Hnd, const char *EvtUrl_const, int *TimeOut, Upnp_SID SubsId)
Registers a control point to receive event notifications from a UPnP device.
Definition upnpapi.cpp:1936
int UpnpVirtualDir_set_GetInfoCallback(VDCallback_GetInfo callback)
Sets the get_info callback function to be used to access a web directory.
Definition upnpapi.cpp:3597
in_port_t LOCAL_PORT_V6_ULA_GUA
IPv6 GUA port for the mini-server.
Definition upnpapi.cpp:149
unsigned gIF_IPV6_ULA_GUA_PREFIX_LENGTH
IPv6 GUA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:147
int UpnpOpenHttpGet(const char *url, void **handle, char **contentType, int *contentLength, int *httpStatus, int timeout)
Gets a file specified in a URL.
Definition upnpapi.cpp:2966
int UpnpNotifyExt(UpnpDevice_Handle Hnd, const char *DevID_const, const char *ServName_const, IXML_Document *PropSet)
Similar to UpnpNotify() except that it takes a DOM document for the event rather than an array of str...
Definition upnpapi.cpp:2342
struct VirtualDirCallbacks virtualDirCallback
This structure is for virtual directory callbacks.
Definition upnpapi.cpp:99
Upnp_Handle_Type GetHandleInfo(UpnpClient_Handle Hnd, Handle_Info **HndInfo)
Get handle information.
Definition upnpapi.cpp:3339
void UpnpThreadDistribution(struct UpnpNonblockParam *Param)
Schedule async functions in threadpool.
Definition upnpapi.cpp:3139
ThreadPool gSendThreadPool
Send thread pool.
Definition upnpapi.cpp:111
char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN]
IPv6 GUA buffer to contain interface IPv6 global-unicast address.
Definition upnpapi.cpp:145
void UpnpSetHostValidateCallback(WebCallback_HostValidate callback, void *cookie)
Set callback for validating HTTP requests HOST header values.
Definition upnpapi.cpp:3587
int UpnpCloseHttpPost(void *handle, int *httpStatus, int timeout)
Sends and receives any pending data, closes the connection with the server, and frees memory allocate...
Definition upnpapi.cpp:2956
int UpnpRegisterRootDevice3(const char *const DescUrl, const Upnp_FunPtr Fun, const void *const Cookie, UpnpDevice_Handle *const Hnd, const int AddressFamily)
Registers one UPnP device object for a specific address family with the UPnP library and get a handle...
Definition upnpapi.cpp:1308
static int UpnpInitStartServers(in_port_t DestPort)
Finishes initializing the UPnP SDK.
Definition upnpapi.cpp:756
int UpnpSendAdvertisementLowPower(UpnpDevice_Handle Hnd, int Exp, int PowerState, int SleepPeriod, int RegistrationState)
Sends out the discovery announcements for all devices and services contained within one root device.
Definition upnpapi.cpp:1721
int UpnpRenewSubscription(UpnpClient_Handle Hnd, int *TimeOut, const Upnp_SID SubsId)
Renews a subscription that is about to expire.
Definition upnpapi.cpp:2179
ThreadPool gRecvThreadPool
Receive thread pool.
Definition upnpapi.cpp:114
int UpnpEnableWebserver(int enable)
Enables or disables the webserver.
Definition upnpapi.cpp:3564
static void free_action_arg(job_arg *arg)
Free memory associated with an action job's argument.
Definition upnpapi.cpp:596
int UpnpOpenHttpPost(const char *url, void **handle, const char *contentType, int contentLength, int timeout)
Makes an HTTP POST request message, opens a connection to the server and sends the POST request to th...
Definition upnpapi.cpp:2942
int UpnpDownloadUrlItem(const char *url, char **outBuf, char *contentType)
Downloads a file specified in a URL.
Definition upnpapi.cpp:3055
void PrintThreadPoolStats(ThreadPool *tp, const char *DbgFileName, int DbgLineNo, const char *msg)
Prints thread pool statistics if DEBUG is enabled. See also #define PrintThreadPoolStats()
Definition upnpapi.cpp:838
int UpnpRegisterRootDevice4(const char *const DescUrl, const Upnp_FunPtr Fun, const void *const Cookie, UpnpDevice_Handle *const Hnd, const int AddressFamily, const char *const LowerDescUrl)
Same as UpnpRegisterRootDevice3() with additional argument to specify a description URL.
Definition upnpapi.cpp:1317
static int UpnpInitPreamble()
Performs the initial steps in initializing the UPnP SDK.
Definition upnpapi.cpp:689
int UpnpCancelHttpGet(void *Handle)
Set the cancel flag of the handle parameter.
Definition upnpapi.cpp:3008
int UpnpReadHttpResponse(void *handle, char *buf, size_t *size, int timeout)
Reads the content of a response using a connection previously created by UpnpOpenHttpConnection().
Definition upnpapi.cpp:3045
int UpnpSetMaxContentLength(size_t contentLength)
Sets the maximum content-length that the SDK will process on an incoming SOAP requests or responses.
Definition upnpapi.cpp:3651
int gAllowLiteralHostRedirection
Allow literal host names redirection to numeric host names.
Definition upnpapi.cpp:129
int UpnpMakeHttpRequest(Upnp_HttpMethod method, const char *url, void *handle, UpnpString *headers, const char *contentType, int contentLength, int timeout)
Makes a HTTP request using a connection previously created by UpnpOpenHttpConnection().
Definition upnpapi.cpp:3024
int PrintHandleInfo(UpnpClient_Handle Hnd)
Print handle info.
Definition upnpapi.cpp:3361
int UpnpUnSubscribe(UpnpClient_Handle Hnd, const Upnp_SID SubsId)
Removes the subscription of a control point from a service previously subscribed to using UpnpSubscri...
Definition upnpapi.cpp:2068
char * UpnpGetServerIp6Address()
Returns the IPv6 link-local listening ip address.
Definition upnpapi.cpp:984
int UpnpOpenHttpGetProxy(const char *url, const char *proxy_str, void **handle, char **contentType, int *contentLength, int *httpStatus, int timeout)
Gets a file specified in a URL through the specified proxy.
Definition upnpapi.cpp:2983
int UpnpRegisterRootDevice2(const Upnp_DescType descriptionType, const char *const description_const, const size_t bufferLen, const int config_baseURL, const Upnp_FunPtr Fun, const void *const Cookie, UpnpDevice_Handle *const Hnd)
Registers one root- or logical-device object with the UPnP Library with additional description and ge...
Definition upnpapi.cpp:1163
Upnp_SID gUpnpSdkNLSuuid
Global variable used in discovery notifications.
Definition upnpapi.cpp:212
pthread_rwlock_t GlobalHndRWLock
rwlock to synchronize handles (root device or control point handle).
Definition upnpapi.cpp:105
unsigned short UpnpGetServerPort()
Returns the internal server IPv4 UPnP listening port.
Definition upnpapi.cpp:948
int UpnpVirtualDir_set_WriteCallback(VDCallback_Write callback)
Sets the write callback function to be used to access a web directory.
Definition upnpapi.cpp:3624
int UpnpWriteHttpPost(void *handle, char *buf, size_t *size, int timeout)
Sends a request to a server to copy the contents of a buffer to the URI specified in the UpnpOpenHttp...
Definition upnpapi.cpp:2952
Upnp_Handle_Type GetDeviceHandleInfoForPath(const char *path, int AddressFamily, UpnpDevice_Handle *device_handle_out, struct Handle_Info **HndInfo, service_info **serv_info)
Retrieves the device handle and information of the first device of the address family specified,...
Definition upnpapi.cpp:3302
int UpnpOpenHttpGetEx(const char *url_str, void **Handle, char **contentType, int *contentLength, int *httpStatus, int lowRange, int highRange, int timeout)
Gets specified number of bytes from a file specified in the URL.
Definition upnpapi.cpp:3001
int UpnpRenewSubscriptionAsync(UpnpClient_Handle Hnd, int TimeOut, Upnp_SID SubsId, Upnp_FunPtr Fun, const void *Cookie_const)
Renews a subscription that is about to expire, generating a callback when the operation is complete.
Definition upnpapi.cpp:2232
char * UpnpGetServerUlaGuaIp6Address()
Returns the IPv6 unique-local or globally-unique listening ip address.
Definition upnpapi.cpp:995
int UpnpUnSubscribeAsync(UpnpClient_Handle Hnd, Upnp_SID SubsId, Upnp_FunPtr Fun, const void *Cookie_const)
Removes a subscription of a control point from a service previously subscribed to using UpnpSubscribe...
Definition upnpapi.cpp:2114
unsigned gIF_IPV6_PREFIX_LENGTH
IPv6 LLA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:140
int UpnpVirtualDir_set_SeekCallback(VDCallback_Seek callback)
Sets the seek callback function to be used to access a web directory.
Definition upnpapi.cpp:3633
int UpnpFinish()
Terminates the Linux SDK for UPnP Devices.
Definition upnpapi.cpp:876
int UpnpSetMaxSubscriptions(UpnpDevice_Handle Hnd, int MaxSubscriptions)
Sets the maximum number of subscriptions accepted per service.
Definition upnpapi.cpp:1866
static int UpnpInitMutexes()
Initializes the global mutexes used by the UPnP SDK.
Definition upnpapi.cpp:614
void * gWebCallback_HostValidateCookie
Cookie to the webCallback for HOST validation.
Definition upnpapi.cpp:126
int UpnpVirtualDir_set_ReadCallback(VDCallback_Read callback)
Sets the read callback function to be used to access a web directory.
Definition upnpapi.cpp:3615
unsigned short UpnpGetServerPort6()
Returns the internal server IPv6 link-local (LLA) UPnP listening port.
Definition upnpapi.cpp:955
size_t g_maxContentLength
Maximum content-length (in bytes) that the SDK will process on an incoming packet.
Definition upnpapi.cpp:166
int UpnpSetWebServerRootDir(const char *rootDir)
Sets the document root directory for the internal web server.
Definition upnpapi.cpp:3395
virtualDirList * pVirtualDirList
Pointer to the virtual directory list.
Definition upnpapi.cpp:102
static int GetNameForAlias(char *name, char **alias)
Determines alias for given name which is a file name or URL.
Definition upnpapi.cpp:1511
int g_UpnpSdkEQMaxLen
Global variable to determines the maximum number of events.
Definition upnpapi.cpp:174
int UpnpCloseHttpConnection(void *handle)
Closes the connection created with UpnpOpenHttpConnection() and frees any memory associated with the ...
Definition upnpapi.cpp:3049
in_port_t LOCAL_PORT_V6
IPv6 LLA port for the mini-server.
Definition upnpapi.cpp:142
int UpnpNotify(UpnpDevice_Handle Hnd, const char *DevID_const, const char *ServName_const, const char **VarName_const, const char **NewVal_const, int cVariables)
Sends out an event change notification to all control points subscribed to a particular service.
Definition upnpapi.cpp:2297
int UpnpGetServiceVarStatusAsync(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *VarName_const, Upnp_FunPtr Fun, const void *Cookie_const)
Queries the state of a variable of a service, generating a callback when the operation is complete.
Definition upnpapi.cpp:2829
int UpnpHttpGetProgress(void *Handle, size_t *length, size_t *total)
Retrieve progress information of a http-get transfer.
Definition upnpapi.cpp:3016
int UpnpSetMaxSubscriptionTimeOut(UpnpDevice_Handle Hnd, int MaxSubscriptionTimeOut)
Sets the maximum time-out accepted for a subscription request or renewal.
Definition upnpapi.cpp:1899
static int GetDescDocumentAndURL(Upnp_DescType descriptionType, char *description, int config_baseURL, int AddressFamily, IXML_Document **xmlDoc, char descURL[LINE_SIZE])
Fills the sockadr_in with miniserver information.
Definition upnpapi.cpp:1566
int UpnpReadHttpGet(void *Handle, char *buf, size_t *size, int timeout)
Gets specified number of bytes from a file specified in a URL.
Definition upnpapi.cpp:3012
int UpnpRegisterRootDevice(const char *const DescUrl, const Upnp_FunPtr Fun, const void *const Cookie, UpnpDevice_Handle *const Hnd)
Registers one root- or logical-device object with the UPnP Library to get a handle for it.
Definition upnpapi.cpp:1007
int UpnpSendAdvertisement(UpnpDevice_Handle Hnd, int Exp)
Sends out the discovery announcements for all devices and services contained within one root device.
Definition upnpapi.cpp:1715
unsigned short UpnpGetServerUlaGuaPort6()
Returns the internal server IPv6 ULA or GUA UPnP listening port.
Definition upnpapi.cpp:966
int UpnpSdkInit
Global variable to denote the state of Upnp SDK == 0 if uninitialized, == 1 if initialized.
Definition upnpapi.cpp:189
static void get_server_addr(struct sockaddr *serverAddr)
Fill the sockadr with IPv4 miniserver information.
Definition upnpapi.cpp:1537
in_port_t LOCAL_PORT_V4
IPv4 local port for the mini-server.
Definition upnpapi.cpp:156
static int UpnpInitThreadPools()
Initializes the global threadm pools used by the UPnP SDK.
Definition upnpapi.cpp:642
int UpnpSendAction(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *ServiceType_const, const char *DevUDN_const, IXML_Document *Action, IXML_Document **RespNodePtr)
Sends a message to change a state variable in a service.
Definition upnpapi.cpp:2535
int UpnpAddVirtualDir(const char *newDirName, const void *cookie, const void **oldcookie)
Adds a web directory mapping.
Definition upnpapi.cpp:3423
int UpnpSubscribeAsync(UpnpClient_Handle Hnd, const char *EvtUrl_const, int TimeOut, Upnp_FunPtr Fun, const void *Cookie_const)
Performs the same operation as UpnpSubscribe(), but returns immediately and calls the registered call...
Definition upnpapi.cpp:2002
int UpnpSdkDeviceRegisteredV4
Global variable to denote the state of Upnp SDK IPv4 device registration.
Definition upnpapi.cpp:200
Upnp_Handle_Type GetDeviceHandleInfo(UpnpDevice_Handle start, int AddressFamily, UpnpDevice_Handle *device_handle_out, struct Handle_Info **HndInfo)
Retrieves the device handle and information of the first device of the address family specified....
Definition upnpapi.cpp:3265
int UpnpUnRegisterRootDeviceLowPower(UpnpDevice_Handle Hnd, int PowerState, int SleepPeriod, int RegistrationState)
Unregisters a root device registered with UpnpRegisterRootDevice(), UpnpRegisterRootDevice2(),...
Definition upnpapi.cpp:1334
int UpnpSdkClientRegistered
Global variable to denote the state of Upnp SDK client registration.
Definition upnpapi.cpp:194
int UpnpAcceptSubscriptionExt(UpnpDevice_Handle Hnd, const char *DevID_const, const char *ServName_const, IXML_Document *PropSet, const Upnp_SID SubsId)
Similar to UpnpAcceptSubscription() except that it takes a DOM document for the variables to event ra...
Definition upnpapi.cpp:2457
void AutoAdvertise(void *input)
This function is a timer thread scheduled by UpnpSendAdvertisement to the send advetisement again.
Definition upnpapi.cpp:3386
int UpnpUnRegisterRootDevice(UpnpDevice_Handle Hnd)
Unregisters a root device registered with UpnpRegisterRootDevice(), UpnpRegisterRootDevice2(),...
Definition upnpapi.cpp:1328
int UpnpSendActionExAsync(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *ServiceType_const, const char *DevUDN_const, IXML_Document *Header, IXML_Document *Act, Upnp_FunPtr Fun, const void *Cookie_const)
Sends a message to change a state variable in a service, generating a callback when the operation is ...
Definition upnpapi.cpp:2717
int UpnpRemoveVirtualDir(const char *dirName)
Removes a web directory mapping made with UpnpAddVirtualDir().
Definition upnpapi.cpp:3498
int UpnpEndHttpRequest(void *handle, int timeout)
Indicates the end of a HTTP request previously made by UpnpMakeHttpRequest().
Definition upnpapi.cpp:3035
void UpnpRemoveAllVirtualDirs()
Removes all web directory mappings.
Definition upnpapi.cpp:3544
int UpnpDownloadXmlDoc(const char *url, IXML_Document **xmlDoc)
Downloads an XML document specified in a URL.
Definition upnpapi.cpp:3077
static void get_server_addr6(struct sockaddr *serverAddr)
Fill the sockadr with IPv6 miniserver information.
Definition upnpapi.cpp:1552
int UpnpWriteHttpRequest(void *handle, char *buf, size_t *size, int timeout)
Writes the content of a HTTP request initiated by a UpnpMakeHttpRequest() call. The end of the conten...
Definition upnpapi.cpp:3031
char gIF_IPV4[INET_ADDRSTRLEN]
IPv4 buffer to contain interface address. (extern'ed in upnp.h)
Definition upnpapi.cpp:152
TimerThread gTimerThread
Global timer thread.
Definition upnpapi.cpp:108
static void free_advertise_arg(job_arg *arg)
Free memory associated with advertise job's argument.
Definition upnpapi.cpp:584
int UpnpVirtualDir_set_OpenCallback(VDCallback_Open callback)
Sets the open callback function to be used to access a web directory.
Definition upnpapi.cpp:3606
char gIF_NAME[LINE_SIZE]
Buffer to contain used network interface name. (extern'ed in upnp.h)
Definition upnpapi.cpp:133
unsigned gIF_INDEX
Index/scope-id from the used network interface.
Definition upnpapi.cpp:135
ThreadPool gMiniServerThreadPool
Mini server thread pool.
Definition upnpapi.cpp:117
membuffer gWebserverCorsString
Definition webserver.hpp:46
char gIF_IPV4_NETMASK[INET_ADDRSTRLEN]
IPv4 buffer to contain interface netmask. (extern'ed in upnp.h)
Definition upnpapi.cpp:154
int g_UpnpSdkEQMaxAge
Global variable to determine the maximum number of seconds which an event can spend on a subscription...
Definition upnpapi.cpp:185
int UpnpSendActionEx(UpnpClient_Handle Hnd, const char *ActionURL_const, const char *ServiceType_const, const char *DevUDN_const, IXML_Document *Header, IXML_Document *Action, IXML_Document **RespNodePtr)
Sends a message to change a state variable in a service.
Definition upnpapi.cpp:2583
char gIF_IPV6[INET6_ADDRSTRLEN]
IPv6 LLA buffer to contain interface address. (extern'ed in upnp.h)
Definition upnpapi.cpp:138
int UpnpSdkDeviceregisteredV6
Global variable to denote the state of Upnp SDK IPv6 device registration.
Definition upnpapi.cpp:206
void UpnpSetAllowLiteralHostRedirection(int enable)
Enable or disable literal IP redirection.
Definition upnpapi.cpp:3593
Upnp_Handle_Type GetClientHandleInfo(UpnpClient_Handle *client_handle_out, struct Handle_Info **HndInfo)
Get client handle info.
Definition upnpapi.cpp:3245
int UpnpIsWebserverEnabled()
Returns the status of the webserver.
Definition upnpapi.cpp:3580
int UpnpOpenHttpConnection(const char *url, void **handle, int timeout)
Opens a connection to the server.
Definition upnpapi.cpp:3020
int UpnpSetWebServerCorsString(const char *corsString)
Assign the Access-Control-Allow-Origin specfied by the input const char* cors_string parameter to the...
Definition upnpapi.cpp:3410
WebServerState bWebServerState
Flag to indicate the state of web server.
Definition upnpapi.cpp:120
char * UpnpGetServerIpAddress()
Returns the local IPv4 listening ip address.
Definition upnpapi.cpp:977
int UpnpGetHttpResponse(void *handle, UpnpString *headers, char **contentType, int *contentLength, int *httpStatus, int timeout)
Gets the response from the server using a connection previously created by UpnpOpenHttpConnection().
Definition upnpapi.cpp:3039
int UpnpVirtualDir_set_CloseCallback(VDCallback_Close callback)
Sets the close callback function to be used to access a web directory.
Definition upnpapi.cpp:3642
Inititalize the compatible library before it can be used.
IXML_Document * Act
UpnpNonblockParam
Definition upnpapi.hpp:275
Upnp_Handle_Type HType
Handle Type.
Definition upnpapi.hpp:87
IXML_Document * Header
UpnpNonblockParam
Definition upnpapi.hpp:274
char * Cookie
UpnpNonblockParam
Definition upnpapi.hpp:272
IXML_NodeList * ServiceList
List of services in the description document.
Definition upnpapi.hpp:108
int aliasInstalled
0 = not installed; otherwise installed.
Definition upnpapi.hpp:90
int Handle
UpnpNonblockParam
Definition upnpapi.hpp:262
#define HandleLock()
HandleLock.
Definition upnpapi.hpp:140
Upnp_FunPtr Fun
UpnpNonblockParam
Definition upnpapi.hpp:273
Upnp_Handle_Type
Definition upnpapi.hpp:77
char Url[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:270
GenlibClientSubscription * ClientSubList
Client subscription list.
Definition upnpapi.hpp:120
#define DEFAULT_MAXAGE
DEFAULT_MAXAGE.
Definition upnpapi.hpp:58
service_table ServiceTable
Table holding subscriptions and URL information.
Definition upnpapi.hpp:110
int SleepPeriod
Sleep Period as defined by UPnP Low Power.
Definition upnpapi.hpp:102
#define DEFAULT_MX
DEFAULT_MX.
Definition upnpapi.hpp:55
PUPNP_API unsigned gIF_INDEX
Index/scope-id from the used network interface.
Definition upnpapi.cpp:135
char LowerDescURL[LINE_SIZE]
URL for the use of SSDP when answering to legacy CPs (CP searching for a v1 when the device is v2).
Definition upnpapi.hpp:96
int RegistrationState
Registration State as defined by UPnP Low Power.
Definition upnpapi.hpp:103
PUPNP_API char gIF_IPV4[INET_ADDRSTRLEN]
IPv4 buffer to contain interface address. (extern'ed in upnp.h)
Definition upnpapi.cpp:152
char DescURL[LINE_SIZE]
URL for the use of SSDP.
Definition upnpapi.hpp:95
PUPNP_API char gIF_IPV6[INET6_ADDRSTRLEN]
IPv6 LLA buffer to contain interface address. (extern'ed in upnp.h)
Definition upnpapi.cpp:138
PUPNP_API unsigned gIF_IPV6_ULA_GUA_PREFIX_LENGTH
IPv6 GUA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:147
Upnp_SID SubsId
UpnpNonblockParam
Definition upnpapi.hpp:271
#define HandleUnlock()
HandleUnlock.
Definition upnpapi.hpp:149
IXML_Document * DescDocument
Description parsed in terms of DOM document.
Definition upnpapi.hpp:105
PUPNP_API char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN]
IPv6 GUA buffer to contain interface IPv6 global-unicast address.
Definition upnpapi.cpp:145
UpnpFunName FunName
UpnpNonblockParam
Definition upnpapi.hpp:261
int TimeOut
UpnpNonblockParam
Definition upnpapi.hpp:263
int PowerState
Power State as defined by UPnP Low Power.
Definition upnpapi.hpp:101
WebServerState
Possible status of the internal webserver.
Definition upnpapi.hpp:284
PUPNP_API unsigned gIF_IPV6_PREFIX_LENGTH
IPv6 LLA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:140
char * Cookie
???
Definition upnpapi.hpp:89
Upnp_FunPtr Callback
Callback function pointer.
Definition upnpapi.hpp:88
constexpr int NUM_HANDLE
Maximal number of available UPnP Unit handles.
Definition upnpapi.hpp:66
int MaxSubscriptionTimeOut
???
Definition upnpapi.hpp:112
int MaxSubscriptions
???
Definition upnpapi.hpp:111
LinkedList SsdpSearchList
Active SSDP searches.
Definition upnpapi.hpp:121
IXML_NodeList * DeviceList
List of devices in the description document.
Definition upnpapi.hpp:106
int MaxAge
Advertisement timeout.
Definition upnpapi.hpp:100
PUPNP_API char gIF_NAME[LINE_SIZE]
Buffer to contain used network interface name. (extern'ed in upnp.h)
Definition upnpapi.cpp:133
char VarName[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:264
int DeviceAf
Address family: AF_INET6 or AF_INET.
Definition upnpapi.hpp:113
char ServiceType[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:268
PUPNP_API char gIF_IPV4_NETMASK[INET_ADDRSTRLEN]
IPv4 buffer to contain interface netmask. (extern'ed in upnp.h)
Definition upnpapi.cpp:154
#define HandleReadLock()
HandleReadLock.
Definition upnpapi.hpp:146
Data to be stored in handle table for Handle Info.
Definition upnpapi.hpp:86
UpnpNonblockParam.
Definition upnpapi.hpp:258
UPnPsdk_VIS void UpnpPrintf(Upnp_LogLevel DLevel, Dbg_Module Module, const char *DbgFileName, int DbgLineNo, const char *FmtStr,...)
Prints the debug statement.
UPnPsdk_VIS int UpnpInitLog(void)
Initialize the log files.
Definition upnpdebug.cpp:77
UPnPsdk_VIS void UpnpCloseLog(void)
Closes the log files.
Configure the full URL for the description document.
int configure_urlbase(IXML_Document *doc, const sockaddr *serverAddr, const char *alias, time_t last_modified, char docURL[LINE_SIZE])
Configure the full URL for the description document.
Manage UUIDs.
void uuidMutexInit()
Initialize mutex for synchronizing the uuid creation process.
Definition uuid.cpp:198
void upnp_uuid_unpack(uuid_upnp *u, char *out)
Unpack a UUID.
Definition uuid.cpp:242
int uuidMutexDestroy()
Destroy mutex for synchronizing the uuid creation process.
Definition uuid.cpp:202
int uuid_create(uuid_upnp *uid)
Generate a UUID.
Definition uuid.cpp:211
uuid UPNP
Definition uuid.hpp:42