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-06-08
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 2024-10-26, ver 1.14.20
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 <csignal>
74#include <cstdlib>
75#include <cstring>
76
77#ifdef _WIN32
78/* Do not include these files */
79#else
80#include <ifaddrs.h>
81#include <sys/ioctl.h>
82#include <sys/types.h>
83#endif
84
85namespace compa {
86namespace {
87
89pthread_mutex_t sdkInit_mutex = PTHREAD_MUTEX_INITIALIZER;
90
93
94
123 std::string_view a_iface = "") //
124{
125 TRACE("Executing compa::UpnpGetIfInfo()")
126 UPnPsdk::CNetadapter nadaptObj;
127 try {
128 nadaptObj.get_first(); // May throw exception
129
130 if (!nadaptObj.find_first(a_iface) &&
131 !nadaptObj.find_first(
132 static_cast<unsigned int>(std::stoi(std::string(a_iface))))) {
133 UPnPsdk_LOGERR("MSG1033") "Local network interface \""
134 << a_iface << "\" not found.\n";
136 }
137
138 // Get gIF_NAME and gIF_INDEX
139 ::memset(gIF_NAME, 0, sizeof(gIF_NAME));
140 ::strncpy(gIF_NAME, nadaptObj.name().c_str(), sizeof(gIF_NAME) - 1);
141 gIF_INDEX = nadaptObj.index();
142
143 // With default lookup restrict finding to the current selected adapter.
144 if (a_iface.empty())
145 nadaptObj.find_first(gIF_INDEX);
146
147 ::memset(gIF_IPV6, 0, sizeof(gIF_IPV6));
148 ::memset(gIF_IPV6_ULA_GUA, 0, sizeof(gIF_IPV6_ULA_GUA));
149 ::memset(gIF_IPV4, 0, sizeof(gIF_IPV4));
150 ::memset(gIF_IPV4_NETMASK, 0, sizeof(gIF_IPV4_NETMASK));
151
152 UPnPsdk::SSockaddr saObj;
153 do {
154 nadaptObj.sockaddr(saObj);
155 switch (saObj.ss.ss_family) {
156 case AF_INET6:
157 // The loopback address belongs to link-local unicast
158 // addresses.
159 if (gIF_IPV6[0] == '\0' &&
160 (IN6_IS_ADDR_LINKLOCAL(&saObj.sin6.sin6_addr) ||
161 IN6_IS_ADDR_LOOPBACK(&saObj.sin6.sin6_addr))) {
162 // Strip leading bracket on copying.
163 ::strncpy(gIF_IPV6, saObj.netaddr().c_str() + 1,
164 sizeof(gIF_IPV6) - 1);
165 // Strip trailing scope id if any.
166 if (char* chptr{::strchr(gIF_IPV6, '%')})
167 *chptr = '\0';
168 // Strip trailing bracket if any.
169 else if (char* chptr{::strchr(gIF_IPV6, ']')})
170 *chptr = '\0';
171 gIF_IPV6_PREFIX_LENGTH = nadaptObj.bitmask();
172 } else if (gIF_IPV6_ULA_GUA[0] == '\0') {
173 // Strip leading bracket on copying.
174 ::strncpy(gIF_IPV6_ULA_GUA, saObj.netaddr().c_str() + 1,
175 sizeof(gIF_IPV6_ULA_GUA) - 1);
176 // Strip trailing scope id if any.
177 if (char* chptr{::strchr(gIF_IPV6, '%')})
178 *chptr = '\0';
179 // Strip trailing bracket if any.
180 else if (char* chptr{::strchr(gIF_IPV6_ULA_GUA, ']')})
181 *chptr = '\0';
183 }
184 break;
185
186 case AF_INET:
187 if (gIF_IPV4[0] == '\0') {
188 ::strncpy(gIF_IPV4, saObj.netaddr().c_str(),
189 sizeof(gIF_IPV4) - 1);
190 nadaptObj.socknetmask(saObj);
191 ::strncpy(gIF_IPV4_NETMASK, saObj.netaddr().c_str(),
192 sizeof(gIF_IPV4_NETMASK) - 1);
193 }
194 break;
195
196 default:
197 UPnPsdk_LOGCRIT("MSG1029") "Unsupported address family("
198 << saObj.ss.ss_family << "), only AF_INET6(" << AF_INET6
199 << ") or AF_INET(" << AF_INET << ") are valid.\n";
201 } // switch
202
203 } while (nadaptObj.find_next() &&
204 (gIF_IPV6[0] == '\0' || gIF_IPV6_ULA_GUA[0] == '\0' ||
205 gIF_IPV4[0] == '\0'));
206
207 } catch (const std::exception& ex) {
208 UPnPsdk_LOGCATCH("MSG1006") "catched next line...\n" << ex.what();
210 }
211
212 return UPNP_E_SUCCESS;
213}
214
215} // namespace
216} // namespace compa
217
218namespace { // anonymous namespace for file scoped old upnpapi items.
219
221// Compatible call mainly used for Unit Tests.
222[[maybe_unused]] int UpnpGetIfInfo(
224 const char* a_IFace) {
225 TRACE("Executing ::UpnpGetIfInfo()")
226 return compa::UpnpGetIfInfo(a_IFace == nullptr ? "" : a_IFace);
227}
229
230} // anonymous namespace
231
232
233#if !defined(ifr_netmask) || defined(DOXYGEN_RUN) // it's a define if exists
236#define ifr_netmask ifr_addr
237#endif
238
239#if !defined(IN6_IS_ADDR_ULA) || defined(DOXYGEN_RUN)
241#define IN6_IS_ADDR_ULA(a) \
242 ((((__const uint32_t*)(a))[0] & htonl((uint32_t)0xfe000000)) == \
243 htonl((uint32_t)0xfc000000))
244#endif /* IN6_IS_ADDR_ULA */
245
248
251
253pthread_rwlock_t GlobalHndRWLock;
254
257
260
263
266
268WebServerState bWebServerState = WEB_SERVER_DISABLED;
269
272
275
278
280char gIF_NAME[LINE_SIZE] = {'\0'};
281
284char gIF_IPV4[INET_ADDRSTRLEN] = {'\0'};
285
288char gIF_IPV4_NETMASK[INET_ADDRSTRLEN] = {'\0'};
289
292char gIF_IPV6[INET6_ADDRSTRLEN] = {'\0'};
293
296
299unsigned gIF_INDEX;
300// unsigned gIF_INDEX = ~0u; // Use complement of 0 because 0 may be a used
301// index.
302
305char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN] = {'\0'};
306
309
312
315
318
321
328
336
347
351
356
362
368
369#ifdef COMPA_HAVE_OPTION_SSDP
374#endif
375
377typedef union {
379 struct {
380 int handle;
381 int eventId;
382 void* Event;
383 } advertise;
385 struct UpnpNonblockParam action;
386} job_arg;
387
388#ifdef COMPA_HAVE_DEVICE_SSDP // Needed to compile with warings as errors --Ingo
392static void free_advertise_arg(job_arg* arg) {
393 if (arg->advertise.Event) {
394 free(arg->advertise.Event);
395 }
396 free(arg);
397}
398#endif
399
400#ifdef COMPA_HAVE_CTRLPT_SOAP
404static void free_action_arg(job_arg* arg) {
405 if (arg->action.Header) {
407 }
408 if (arg->action.Act) {
410 }
411 free(arg);
412}
413#endif
414
415
422static int UpnpInitMutexes() {
423#ifdef __CYGWIN__
424 /* On Cygwin, pthread_mutex_init() fails without this memset. */
425 /* TODO: Fix Cygwin so we don't need this memset(). */
426 memset(&GlobalHndRWLock, 0, sizeof(GlobalHndRWLock));
427#endif
428 if (pthread_rwlock_init(&GlobalHndRWLock, NULL) != 0) {
429 return UPNP_E_INIT_FAILED;
430 }
431#ifdef COMPA_HAVE_OPTION_SSDP
432 // Mutex to synchronize the uuid creation process.
434#endif
435 /* initialize subscribe mutex. */
436#ifdef COMPA_HAVE_CTRLPT_GENA
437 if (clientSubscribeMutexInit() != 0) {
438 return UPNP_E_INIT_FAILED;
439 }
440#endif
441 return UPNP_E_SUCCESS;
442}
443
451 int ret = UPNP_E_SUCCESS;
452 ThreadPoolAttr attr;
453
454 TPAttrInit(&attr);
461
463 ret = UPNP_E_INIT_FAILED;
464 goto exit_function;
465 }
466
468 ret = UPNP_E_INIT_FAILED;
469 goto exit_function;
470 }
471
473 ret = UPNP_E_INIT_FAILED;
474 goto exit_function;
475 }
476
477exit_function:
478 if (ret != UPNP_E_SUCCESS) {
479 UpnpSdkInit = 0;
480 UpnpFinish();
481 }
482
483 return ret;
484}
485
497static int UpnpInitPreamble() {
498 TRACE("Executing UpnpInitPreamble()")
499 int retVal = UPNP_E_SUCCESS;
500
501 /* needed by SSDP or other parts. */
502 srand((unsigned int)time(NULL));
503
504 /* Initialize debug output. */
505 retVal = UpnpInitLog();
506 if (retVal != UPNP_E_SUCCESS) {
507 /* UpnpInitLog does not return a valid UPNP_E_*. */
508 return UPNP_E_INIT_FAILED;
509 }
510
511 /* Initialize SDK global mutexes. */
512 retVal = UpnpInitMutexes();
513 if (retVal != UPNP_E_SUCCESS) {
514 return retVal;
515 }
516
517#ifdef COMPA_HAVE_OPTION_SSDP
518 /* Create the NLS uuid. */
519 uuid_upnp nls_uuid;
520 uuid_create(&nls_uuid);
522#endif
523
524 /* Initializes the handle list. */
525 HandleLock();
526 for (int i{0}; i < NUM_HANDLE; ++i) {
527 compa::HandleTable[i] = nullptr;
528 }
529 HandleUnlock();
530
531 /* Initialize SDK global thread pools. */
532 retVal = UpnpInitThreadPools();
533 if (retVal != UPNP_E_SUCCESS) {
534 return retVal;
535 }
536
537#ifdef COMPA_HAVE_DEVICE_SOAP
539#endif
540
541#ifdef COMPA_HAVE_DEVICE_GENA
543#endif
544
545 /* Initialize the SDK timer thread. */
547 if (retVal != UPNP_E_SUCCESS) {
548 UpnpFinish();
549
550 return retVal;
551 }
552
553 return UPNP_E_SUCCESS;
554}
555
566 [[maybe_unused]] in_port_t DestPort) {
567 UPnPsdk_LOGINFO("MSG1061") "Executing...\n";
568 int retVal;
569
570#ifdef COMPA_HAVE_MINISERVER
571 LOCAL_PORT_V4 = DestPort;
572 LOCAL_PORT_V6 = DestPort;
573 LOCAL_PORT_V6_ULA_GUA = DestPort;
574 retVal =
576 if (retVal != UPNP_E_SUCCESS) {
577 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
578 "Miniserver failed to start\n");
579 UpnpFinish();
580 return retVal;
581 }
582#endif
583
584 retVal = UpnpEnableWebserver(WEB_SERVER_ENABLED);
585 if (retVal != UPNP_E_SUCCESS) {
586 UpnpFinish();
587 return retVal;
588 }
589
590 UPnPsdk_LOGINFO("MSG1066") "Finished.\n";
591 return UPNP_E_SUCCESS;
592}
593
594int UpnpInit2(const char* IfName, unsigned short DestPort) {
595 UPnPsdk_LOGINFO("MSG1096") "Executing...\n";
596 int retVal;
597
598 // The mutex must be initialized.
599 if (pthread_mutex_lock(&compa::sdkInit_mutex) != 0) {
600 retVal = UPNP_E_INIT_FAILED;
601 goto exit_function;
602 }
603
604 /* Check if we're already initialized. */
605 if (UpnpSdkInit == 1) {
606 retVal = UPNP_E_INIT;
607 goto exit_function;
608 }
609
610 /* Set the UpnpSdkInit flag to 1 to indicate we're successfully
611 * initialized. */
612 UpnpSdkInit = 1;
613
614 /* Perform initialization preamble. */
615 retVal = UpnpInitPreamble();
616 if (retVal != UPNP_E_SUCCESS) {
617 goto exit_function;
618 }
619
620 /* Retrieve interface information (Addresses, index, etc). */
621 retVal = compa::UpnpGetIfInfo(IfName == nullptr ? "" : IfName);
622 if (retVal != UPNP_E_SUCCESS) {
623 goto exit_function;
624 }
625
626 /* Finish initializing the SDK. */
627 retVal = UpnpInitStartServers(DestPort);
628 if (retVal != UPNP_E_SUCCESS) {
629 goto exit_function;
630 }
631
632exit_function:
633 if (retVal != UPNP_E_SUCCESS && retVal != UPNP_E_INIT) {
634 UpnpFinish();
635 }
636 pthread_mutex_unlock(&compa::sdkInit_mutex);
637 return retVal;
638}
639
640#ifdef DEBUG
647 ThreadPool* tp,
648 const char* DbgFileName,
650 int DbgLineNo,
652 const char* msg) {
653 ThreadPoolStats stats;
654 ThreadPoolGetStats(tp, &stats);
655 UpnpPrintf(UPNP_INFO, API, DbgFileName, DbgLineNo,
656 "%s\n"
657 "High Jobs pending: %d\n"
658 "Med Jobs Pending: %d\n"
659 "Low Jobs Pending: %d\n"
660 "Average wait in High Q in milliseconds: %lf\n"
661 "Average wait in Med Q in milliseconds: %lf\n"
662 "Average wait in Low Q in milliseconds: %lf\n"
663 "Max Threads Used: %d\n"
664 "Worker Threads: %d\n"
665 "Persistent Threads: %d\n"
666 "Idle Threads: %d\n"
667 "Total Threads: %d\n"
668 "Total Work Time: %lf\n"
669 "Total Idle Time: %lf\n",
670 msg, stats.currentJobsHQ, stats.currentJobsMQ,
671 stats.currentJobsLQ, stats.avgWaitHQ, stats.avgWaitMQ,
672 stats.avgWaitLQ, stats.maxThreads, stats.workerThreads,
673 stats.persistentThreads, stats.idleThreads, stats.totalThreads,
674 stats.totalWorkTime, stats.totalIdleTime);
675}
676#else
679#define PrintThreadPoolStats(tp, DbgFileName, DbgLineNo, msg) \
680 do { \
681 } while (0)
682#endif /* DEBUG */
683
685 TRACE("Executing UpnpFinish()")
686 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
687 "Inside UpnpFinish: UpnpSdkInit is %d\n", UpnpSdkInit);
688#ifdef COMPA_HAVE_DEVICE_SSDP
689 UpnpDevice_Handle device_handle;
690#endif
691#ifdef COMPA_HAVE_CTRLPT_SSDP
692 UpnpClient_Handle client_handle;
693#endif
694 [[maybe_unused]] struct Handle_Info* temp{nullptr};
695#ifdef UPnPsdk_HAVE_OPENSSL
696 freeSslCtx();
697#endif
698 if (UpnpSdkInit != 1)
699 return UPNP_E_FINISH;
700 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
701 "UpnpFinish: UpnpSdkInit is ONE\n");
702 // May be usable for DEBUG:
703 // PrintThreadPoolStats(&gSendThreadPool, __FILE__, __LINE__,
704 // "Send Thread Pool");
705 // PrintThreadPoolStats(&gRecvThreadPool, __FILE__, __LINE__,
706 // "Recv Thread Pool");
707 // PrintThreadPoolStats(&gMiniServerThreadPool, __FILE__, __LINE__,
708 // "MiniServer Thread Pool");
709#ifdef COMPA_HAVE_DEVICE_SSDP
710 while (GetDeviceHandleInfo(0, AF_INET, &device_handle, &temp) ==
711 HND_DEVICE) {
712 UpnpUnRegisterRootDevice(device_handle);
713 }
714 while (GetDeviceHandleInfo(0, AF_INET6, &device_handle, &temp) ==
715 HND_DEVICE) {
716 UpnpUnRegisterRootDevice(device_handle);
717 }
718#endif
719#ifdef COMPA_HAVE_CTRLPT_SSDP
720 while (HND_CLIENT == GetClientHandleInfo(&client_handle, &temp)) {
721 UpnpUnRegisterClient(client_handle);
722 }
723#endif
725#ifdef COMPA_HAVE_MINISERVER
727#endif
728#ifdef COMPA_HAVE_WEBSERVER
730#endif
732 PrintThreadPoolStats(&gMiniServerThreadPool, __FILE__, __LINE__,
733 "MiniServer Thread Pool");
735 PrintThreadPoolStats(&gSendThreadPool, __FILE__, __LINE__,
736 "Send Thread Pool");
738 PrintThreadPoolStats(&gRecvThreadPool, __FILE__, __LINE__,
739 "Recv Thread Pool");
740#ifdef COMPA_HAVE_CTRLPT_GENA
742#endif
743 pthread_rwlock_destroy(&GlobalHndRWLock);
744#ifdef COMPA_HAVE_OPTION_SSDP
745 uuidMutexDestroy(); // May fail but not checked due to compatibility.
746#endif
747 UpnpRemoveAllVirtualDirs(); /* remove all virtual dirs */
748 UpnpSdkInit = 0;
749 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
750 "Exiting UpnpFinish: UpnpSdkInit is :%d:\n", UpnpSdkInit);
751 UpnpCloseLog();
752
753 return UPNP_E_SUCCESS;
754}
755
756unsigned short UpnpGetServerPort() {
757 if (UpnpSdkInit != 1)
758 return 0u;
759
760 return LOCAL_PORT_V4;
761}
762
763unsigned short UpnpGetServerPort6() {
764#ifdef UPNP_ENABLE_IPV6
765 if (UpnpSdkInit != 1)
766 return 0u;
767
768 return LOCAL_PORT_V6;
769#else
770 return 0u;
771#endif
772}
773
774unsigned short UpnpGetServerUlaGuaPort6() {
775#ifdef UPNP_ENABLE_IPV6
776 if (UpnpSdkInit != 1)
777 return 0u;
778
780#else
781 return 0u;
782#endif
783}
784
786 if (UpnpSdkInit != 1)
787 return NULL;
788
789 return gIF_IPV4;
790}
791
793#ifdef UPNP_ENABLE_IPV6
794 if (UpnpSdkInit != 1)
795 return NULL;
796
797 return gIF_IPV6;
798#else
799 return NULL;
800#endif
801}
802
804#ifdef UPNP_ENABLE_IPV6
805 if (UpnpSdkInit != 1)
806 return NULL;
807
808 return gIF_IPV6_ULA_GUA;
809#else
810 return NULL;
811#endif
812}
813
821#if defined(COMPA_HAVE_DEVICE_SSDP) || defined(COMPA_HAVE_CTRLPT_SSDP)
822static int GetFreeHandle() {
823 // Handle 0 is not used as NULL translates to 0 when passed as a handle
824 int i = 1;
825
826 while (i < NUM_HANDLE && compa::HandleTable[i] != nullptr)
827 ++i;
828 if (i == NUM_HANDLE)
829 return UPNP_E_OUTOF_HANDLE;
830 else
831 return i;
832}
833
839static int FreeHandle(
841 int Upnp_Handle) {
842 int ret = UPNP_E_INVALID_HANDLE;
843
844 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
845 "FreeHandle: entering, Handle is %d\n", Upnp_Handle);
846 if (Upnp_Handle < 1 || Upnp_Handle >= NUM_HANDLE) {
847 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
848 "FreeHandle: Handle %d is out of range\n", Upnp_Handle);
849 } else if (compa::HandleTable[Upnp_Handle] == nullptr) {
850 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
851 "FreeHandle: compa::HandleTable[%d] is nullptr\n",
852 Upnp_Handle);
853 } else {
854 free(compa::HandleTable[Upnp_Handle]);
855 compa::HandleTable[Upnp_Handle] = nullptr;
856 ret = UPNP_E_SUCCESS;
857 }
858 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
859 "FreeHandle: exiting, ret = %d.\n", ret);
860
861 return ret;
862}
863#endif // defined(COMPA_HAVE_DEVICE_SSDP) || defined(COMPA_HAVE_CTRLPT_SSDP)
864
865#ifdef COMPA_HAVE_DEVICE_SSDP
866int UpnpRegisterRootDevice(const char* const DescUrl, const Upnp_FunPtr Fun,
867 const void* const Cookie,
868 UpnpDevice_Handle* const Hnd) {
869 struct Handle_Info* HInfo = NULL;
870 int retVal = 0;
871#ifdef COMPA_HAVE_DEVICE_GENA
872 int hasServiceTable{0};
873#endif
874 HandleLock();
875
876 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
877 "Inside UpnpRegisterRootDevice\n");
878
879 if (UpnpSdkInit != 1) {
880 retVal = UPNP_E_FINISH;
881 goto exit_function;
882 }
883
884 if (Hnd == NULL || Fun == NULL || DescUrl == NULL ||
885 strlen(DescUrl) == (size_t)0) {
886 retVal = UPNP_E_INVALID_PARAM;
887 goto exit_function;
888 }
889
890 *Hnd = GetFreeHandle();
891 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
892 retVal = UPNP_E_OUTOF_MEMORY;
893 goto exit_function;
894 }
895
896 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
897 if (HInfo == NULL) {
898 retVal = UPNP_E_OUTOF_MEMORY;
899 goto exit_function;
900 }
901 memset(HInfo, 0, sizeof(struct Handle_Info));
902 compa::HandleTable[*Hnd] = HInfo;
903
904 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Root device URL is %s\n",
905 DescUrl);
906
907 HInfo->aliasInstalled = 0;
908 HInfo->HType = HND_DEVICE;
909 strncpy(HInfo->DescURL, DescUrl, sizeof(HInfo->DescURL) - 1);
910 strncpy(HInfo->LowerDescURL, DescUrl, sizeof(HInfo->LowerDescURL) - 1);
911 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
912 "Following Root Device URL will be used when answering to "
913 "legacy CPs %s\n",
914 HInfo->LowerDescURL);
915 HInfo->Callback = Fun;
916 HInfo->Cookie = (char*)Cookie;
917 HInfo->MaxAge = DEFAULT_MAXAGE;
918 HInfo->DeviceList = NULL;
919 HInfo->ServiceList = NULL;
920 HInfo->DescDocument = NULL;
921#ifdef COMPA_HAVE_CTRLPT_SSDP
922 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
923 HInfo->ClientSubList = NULL;
924#endif
927 HInfo->DeviceAf = AF_INET;
928
929 retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
930 if (retVal != UPNP_E_SUCCESS) {
931 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
932 "UpnpRegisterRootDevice: error downloading Document: "
933 "%d\n",
934 retVal);
935#ifdef COMPA_HAVE_CTRLPT_SSDP
936 ListDestroy(&HInfo->SsdpSearchList, 0);
937#endif
938 FreeHandle(*Hnd);
939 goto exit_function;
940 }
941 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
942 "UpnpRegisterRootDevice: Valid Description\n"
943 "UpnpRegisterRootDevice: DescURL : %s\n",
944 HInfo->DescURL);
945
946 HInfo->DeviceList =
948 if (!HInfo->DeviceList) {
949#ifdef COMPA_HAVE_CTRLPT_SSDP
950 ListDestroy(&HInfo->SsdpSearchList, 0);
951#endif
953 FreeHandle(*Hnd);
954 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
955 "UpnpRegisterRootDevice: No devices found for "
956 "RootDevice\n");
957 retVal = UPNP_E_INVALID_DESC;
958 goto exit_function;
959 }
960
961 HInfo->ServiceList =
962 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
963 if (!HInfo->ServiceList) {
964 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
965 "UpnpRegisterRootDevice: No services found for "
966 "RootDevice\n");
967 }
968
969#ifdef COMPA_HAVE_DEVICE_GENA
970 /*
971 * GENA SET UP
972 */
973 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
974 "UpnpRegisterRootDevice: Gena Check\n");
975 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
976 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
977 &HInfo->ServiceTable, HInfo->DescURL);
978 if (hasServiceTable) {
979 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
980 "UpnpRegisterRootDevice: GENA Service Table\n"
981 "Here are the known services:\n");
982 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
983 } else {
984 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
985 "\nUpnpRegisterRootDevice: Empty service table\n");
986 }
987#endif // COMPA_HAVE_DEVICE_GENA
988
990
991 retVal = UPNP_E_SUCCESS;
992
993exit_function:
994 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
995 "Exiting RegisterRootDevice, return value == %d\n", retVal);
996 HandleUnlock();
997
998 return retVal;
999}
1000#endif /* COMPA_HAVE_DEVICE_SSDP */
1001
1002#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1006static int GetDescDocumentAndURL(
1007 /* [in] pointer to server address structure. */
1008 Upnp_DescType descriptionType,
1009 /* [in] . */
1010 char* description,
1011 /* [in] . */
1012 int config_baseURL,
1013 /* [in] . */
1014 int AddressFamily,
1015 /* [out] . */
1016 IXML_Document** xmlDoc,
1017 /* [out] . */
1018 char descURL[LINE_SIZE]);
1019
1020int UpnpRegisterRootDevice2(const Upnp_DescType descriptionType,
1021 const char* const description_const,
1022 const size_t bufferLen, /* ignored */
1023 const int config_baseURL, const Upnp_FunPtr Fun,
1024 const void* const Cookie,
1025 UpnpDevice_Handle* const Hnd) {
1026 struct Handle_Info* HInfo = NULL;
1027 int retVal = 0;
1028 char* description = (char*)description_const;
1029 (void)bufferLen;
1030#ifdef COMPA_HAVE_DEVICE_GENA
1031 int hasServiceTable{0};
1032#endif
1033 HandleLock();
1034
1035 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1036 "Inside UpnpRegisterRootDevice2\n");
1037
1038 if (UpnpSdkInit != 1) {
1039 retVal = UPNP_E_FINISH;
1040 goto exit_function;
1041 }
1042
1043 if (Hnd == NULL || Fun == NULL) {
1044 retVal = UPNP_E_INVALID_PARAM;
1045 goto exit_function;
1046 }
1047
1048 *Hnd = GetFreeHandle();
1049 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
1050 retVal = UPNP_E_OUTOF_MEMORY;
1051 goto exit_function;
1052 }
1053
1054 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
1055 if (HInfo == NULL) {
1056 retVal = UPNP_E_OUTOF_MEMORY;
1057 goto exit_function;
1058 }
1059 memset(HInfo, 0, sizeof(struct Handle_Info));
1060 compa::HandleTable[*Hnd] = HInfo;
1061
1062 /* prevent accidental removal of a non-existent alias */
1063 HInfo->aliasInstalled = 0;
1064
1065 retVal =
1066 GetDescDocumentAndURL(descriptionType, description, config_baseURL,
1067 AF_INET, &HInfo->DescDocument, HInfo->DescURL);
1068 if (retVal != UPNP_E_SUCCESS) {
1069 FreeHandle(*Hnd);
1070 goto exit_function;
1071 }
1072
1073#ifdef UPNPLIB_PUPNP_BUG
1074 // Error if compiling old code with build type Release: output may be
1075 // truncated copying 179 bytes from a string of length 179
1076 // [-Werror=stringop-truncation]. We have to fix it here otherwise it won't
1077 // compile. --Ingo
1078 strncpy(HInfo->LowerDescURL, HInfo->DescURL,
1079 sizeof(HInfo->LowerDescURL) - 1);
1080#else
1081 strncpy(HInfo->LowerDescURL, HInfo->DescURL, sizeof(HInfo->LowerDescURL));
1082#endif
1083 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1084 "Following Root Device URL will be used when answering to "
1085 "legacy CPs %s\n",
1086 HInfo->LowerDescURL);
1087 HInfo->aliasInstalled = config_baseURL != 0;
1088 HInfo->HType = HND_DEVICE;
1089 HInfo->Callback = Fun;
1090 HInfo->Cookie = (char*)Cookie;
1091 HInfo->MaxAge = DEFAULT_MAXAGE;
1092 HInfo->DeviceList = NULL;
1093 HInfo->ServiceList = NULL;
1094#ifdef COMPA_HAVE_CTRLPT_SSDP
1095 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1096 HInfo->ClientSubList = NULL;
1097#endif
1100 HInfo->DeviceAf = AF_INET;
1101
1102 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1103 "UpnpRegisterRootDevice2: Valid Description\n"
1104 "UpnpRegisterRootDevice2: DescURL : %s\n",
1105 HInfo->DescURL);
1106
1107 HInfo->DeviceList =
1109 if (!HInfo->DeviceList) {
1110#ifdef COMPA_HAVE_CTRLPT_SSDP
1111 ListDestroy(&HInfo->SsdpSearchList, 0);
1112#endif
1114 FreeHandle(*Hnd);
1115 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1116 "UpnpRegisterRootDevice2: No devices found for "
1117 "RootDevice\n");
1118 retVal = UPNP_E_INVALID_DESC;
1119 goto exit_function;
1120 }
1121
1122 HInfo->ServiceList =
1123 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
1124 if (!HInfo->ServiceList) {
1125 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1126 "UpnpRegisterRootDevice2: No services found for "
1127 "RootDevice\n");
1128 }
1129
1130#ifdef COMPA_HAVE_DEVICE_GENA
1131 /*
1132 * GENA SET UP
1133 */
1134 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1135 "UpnpRegisterRootDevice2: Gena Check\n");
1136 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
1137 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
1138 &HInfo->ServiceTable, HInfo->DescURL);
1139 if (hasServiceTable) {
1140 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1141 "UpnpRegisterRootDevice2: GENA Service Table\n"
1142 "Here are the known services: \n");
1143 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
1144 } else {
1145 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1146 "\nUpnpRegisterRootDevice2: Empty service table\n");
1147 }
1148#endif // COMPA_HAVE_DEVICE_GENA
1149
1151
1152 retVal = UPNP_E_SUCCESS;
1153
1154exit_function:
1155 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1156 "Exiting RegisterRootDevice2, return value == %d\n", retVal);
1157 HandleUnlock();
1158
1159 return retVal;
1160}
1161#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1162
1163#ifdef COMPA_HAVE_DEVICE_SSDP
1164
1165namespace compa {
1166namespace {
1168int UpnpRegisterRootDevice3(const char* const DescUrl, const Upnp_FunPtr Fun,
1169 const void* const Cookie,
1170 UpnpDevice_Handle* const Hnd,
1171 const int AddressFamily,
1172 const char* const LowerDescUrl) {
1173 TRACE("Executing UpnpRegisterRootDevice3() (same as "
1174 "UpnpRegisterRootDevice4())")
1175 Handle_Info* HInfo;
1176 int retVal = 0;
1177#ifdef COMPA_HAVE_DEVICE_GENA
1178 int hasServiceTable{0};
1179#endif
1180 HandleLock();
1181
1182 // Do some basic parameter checks.
1183 if (UpnpSdkInit != 1) {
1184 retVal = UPNP_E_FINISH;
1185 goto exit_function;
1186 }
1187 if (Hnd == nullptr || Fun == nullptr || DescUrl == nullptr ||
1188 strlen(DescUrl) == 0 ||
1189 (AddressFamily != AF_INET && AddressFamily != AF_INET6)) {
1190 retVal = UPNP_E_INVALID_PARAM;
1191 goto exit_function;
1192 }
1193
1194 // Get a UPnP Unit handle and initialize handle info for a UPnP Device.
1195 *Hnd = GetFreeHandle();
1196 if (*Hnd == UPNP_E_OUTOF_HANDLE) {
1197 retVal = UPNP_E_OUTOF_MEMORY;
1198 goto exit_function;
1199 }
1200 HInfo = (Handle_Info*)malloc(sizeof(Handle_Info));
1201 if (HInfo == nullptr) {
1202 retVal = UPNP_E_OUTOF_MEMORY;
1203 goto exit_function;
1204 }
1205 memset(HInfo, 0, sizeof(Handle_Info));
1206 compa::HandleTable[*Hnd] = HInfo;
1207
1208 HInfo->HType = HND_DEVICE; // Set handle info to UPnP Device.
1209
1210 strncpy(HInfo->DescURL, DescUrl, sizeof(HInfo->DescURL) - 1);
1211 if (LowerDescUrl == nullptr)
1212 strncpy(HInfo->LowerDescURL, DescUrl, sizeof(HInfo->LowerDescURL) - 1);
1213 else
1214 strncpy(HInfo->LowerDescURL, LowerDescUrl,
1215 sizeof(HInfo->LowerDescURL) - 1);
1216 UPnPsdk_LOGINFO(
1217 "MSG1050") "Following Root UDevice local URL will be used when "
1218 "responding to requests from control points: "
1219 << HInfo->LowerDescURL << ".\n";
1220 HInfo->Callback = Fun;
1221 HInfo->Cookie = (char*)Cookie;
1222 HInfo->MaxAge = DEFAULT_MAXAGE;
1223 HInfo->DeviceList = nullptr;
1224 HInfo->ServiceList = nullptr;
1225 HInfo->DescDocument = nullptr;
1226#ifdef COMPA_HAVE_CTRLPT_SSDP
1227 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1228 HInfo->ClientSubList = nullptr;
1229#endif
1232 HInfo->DeviceAf = AddressFamily;
1233
1234 // Get own device description from local XML file.
1235 retVal = UpnpDownloadXmlDoc(HInfo->DescURL, &(HInfo->DescDocument));
1236 if (retVal != UPNP_E_SUCCESS) {
1237#ifdef COMPA_HAVE_CTRLPT_SSDP
1238 ListDestroy(&HInfo->SsdpSearchList, 0);
1239#endif
1240 FreeHandle(*Hnd);
1241 goto exit_function;
1242 }
1243 UPnPsdk_LOGINFO(
1244 "MSG1051") "UpnpRegisterRootDevice3(or 4): Valid Description\n"
1245 "UpnpRegisterRootDevice3(or 4): DescURL = "
1246 << HInfo->DescURL << ".\n";
1247
1248 HInfo->DeviceList =
1250 if (!HInfo->DeviceList) {
1251#ifdef COMPA_HAVE_CTRLPT_SSDP
1252 ListDestroy(&HInfo->SsdpSearchList, 0);
1253#endif
1255 FreeHandle(*Hnd);
1256 UPnPsdk_LOGCRIT("MSG1052") "UpnpRegisterRootDevice3(or 4): No devices "
1257 "found for RootDevice.\n";
1258 retVal = UPNP_E_INVALID_DESC;
1259 goto exit_function;
1260 }
1261
1262 HInfo->ServiceList =
1263 ixmlDocument_getElementsByTagName(HInfo->DescDocument, "serviceList");
1264 if (!HInfo->ServiceList) {
1265 UPnPsdk_LOGCRIT(
1266 "MSG1054") "UpnpRegisterRootDevice3(or 4): No services found for "
1267 "RootDevice.\n";
1268 }
1269
1270#ifdef COMPA_HAVE_DEVICE_GENA
1271 /*
1272 * GENA SET UP
1273 */
1274 UPnPsdk_LOGINFO("MSG1055") "UpnpRegisterRootDevice3(or 4): Gena Check.\n";
1275 memset(&HInfo->ServiceTable, 0, sizeof(HInfo->ServiceTable));
1276 hasServiceTable = getServiceTable((IXML_Node*)HInfo->DescDocument,
1277 &HInfo->ServiceTable, HInfo->DescURL);
1278 if (hasServiceTable) {
1279 UPnPsdk_LOGINFO(
1280 "MSG1056") "UpnpRegisterRootDevice3(or 4): GENA Service Table\n"
1281 "Here are the known services:\n";
1282 printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
1283 } else {
1284 UPnPsdk_LOGINFO(
1285 "MSG1062") "\nUpnpRegisterRootDevice3(or 4): Empty service table\n";
1286 }
1287#endif // COMPA_HAVE_CTRLPT_GENA || COMPA_HAVE_DEVICE_GENA
1288
1289 switch (AddressFamily) {
1290 case AF_INET:
1292 break;
1293 default:
1295 }
1296
1297 retVal = UPNP_E_SUCCESS;
1298
1299exit_function:
1300 UPnPsdk_LOGINFO(
1301 "MSG1064") "Exiting UpnpRegisterRootDevice3(or 4), return value == "
1302 << retVal << ".\n";
1303 HandleUnlock();
1304
1305 return retVal;
1306}
1307} // anonymous namespace
1308} // namespace compa
1309
1310// UpnpRegisterRootDevice3() (without LowerDescUrl argument).
1311int UpnpRegisterRootDevice3(const char* const DescUrl, const Upnp_FunPtr Fun,
1312 const void* const Cookie,
1313 UpnpDevice_Handle* const Hnd,
1314 const int AddressFamily) {
1315 return compa::UpnpRegisterRootDevice3(DescUrl, Fun, Cookie, Hnd,
1316 AddressFamily, nullptr);
1317}
1318
1319// Same as UpnpRegisterRootDevice3() but with LowerDescUrl argument.
1320int UpnpRegisterRootDevice4(const char* const DescUrl, const Upnp_FunPtr Fun,
1321 const void* const Cookie,
1322 UpnpDevice_Handle* const Hnd,
1323 const int AddressFamily,
1324 const char* const LowerDescUrl) {
1325 return compa::UpnpRegisterRootDevice3(DescUrl, Fun, Cookie, Hnd,
1326 AddressFamily, LowerDescUrl);
1327}
1328#endif /* COMPA_HAVE_DEVICE_SSDP */
1329
1330#ifdef COMPA_HAVE_DEVICE_SSDP
1332 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1333 "Inside UpnpUnRegisterRootDevice\n");
1334 return UpnpUnRegisterRootDeviceLowPower(Hnd, -1, -1, -1);
1335}
1336
1338 int SleepPeriod, int RegistrationState) {
1339 int retVal = 0;
1340 struct Handle_Info* HInfo = NULL;
1341
1342 if (UpnpSdkInit != 1)
1343 return UPNP_E_FINISH;
1344 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1345 "Inside UpnpUnRegisterRootDeviceLowPower\n");
1346#ifdef COMPA_HAVE_DEVICE_GENA
1348 return UPNP_E_INVALID_HANDLE;
1349#endif
1350
1351 HandleLock();
1352 switch (GetHandleInfo(Hnd, &HInfo)) {
1353 case HND_INVALID:
1354 HandleUnlock();
1355 return UPNP_E_INVALID_HANDLE;
1356 default:
1357 break;
1358 }
1359 HInfo->PowerState = PowerState;
1360 if (SleepPeriod < 0)
1361 SleepPeriod = -1;
1362 HInfo->SleepPeriod = SleepPeriod;
1364 HandleUnlock();
1365
1366 retVal = AdvertiseAndReply(-1, Hnd, (enum SsdpSearchType)0,
1367 (struct sockaddr*)NULL, (char*)NULL, (char*)NULL,
1368 (char*)NULL, HInfo->MaxAge);
1369
1370 HandleLock();
1371 switch (GetHandleInfo(Hnd, &HInfo)) {
1372 case HND_INVALID:
1373 HandleUnlock();
1374 return UPNP_E_INVALID_HANDLE;
1375 default:
1376 break;
1377 }
1381#ifdef COMPA_HAVE_CTRLPT_SSDP
1382 ListDestroy(&HInfo->SsdpSearchList, 0);
1383#endif
1384#ifdef COMPA_HAVE_WEBSERVER
1385 if (HInfo->aliasInstalled)
1386 web_server_set_alias(NULL, NULL, 0, 0);
1387#endif
1388 switch (HInfo->DeviceAf) {
1389 case AF_INET:
1391 break;
1392 case AF_INET6:
1394 break;
1395 default:
1396 break;
1397 }
1398 FreeHandle(Hnd);
1399 HandleUnlock();
1400
1401 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
1402 "Exiting UpnpUnRegisterRootDeviceLowPower\n");
1403
1404 return retVal;
1405}
1406#endif /* COMPA_HAVE_DEVICE_SSDP */
1407
1408#ifdef COMPA_HAVE_CTRLPT_SSDP
1410 UpnpClient_Handle* Hnd) {
1411 struct Handle_Info* HInfo;
1412
1413 if (UpnpSdkInit != 1)
1414 return UPNP_E_FINISH;
1415 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1416 "Inside UpnpRegisterClient \n");
1417 if (Fun == NULL || Hnd == NULL)
1418 return UPNP_E_INVALID_PARAM;
1419
1420 HandleLock();
1421 if ((NUM_HANDLE - 1) <=
1424 HandleUnlock();
1426 }
1427 if ((*Hnd = GetFreeHandle()) == UPNP_E_OUTOF_HANDLE) {
1428 HandleUnlock();
1429 return UPNP_E_OUTOF_MEMORY;
1430 }
1431 HInfo = (struct Handle_Info*)malloc(sizeof(struct Handle_Info));
1432 if (HInfo == NULL) {
1433 HandleUnlock();
1434 return UPNP_E_OUTOF_MEMORY;
1435 }
1436 HInfo->HType = HND_CLIENT;
1437 HInfo->Callback = Fun;
1438 HInfo->Cookie = (char*)Cookie;
1439 HInfo->ClientSubList = NULL;
1440 ListInit(&HInfo->SsdpSearchList, NULL, NULL);
1441#ifdef COMPA_HAVE_DEVICE_SSDP
1442 HInfo->MaxAge = 0;
1445#endif
1446 compa::HandleTable[*Hnd] = HInfo;
1448 HandleUnlock();
1449
1450 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1451 "Exiting UpnpRegisterClient \n");
1452
1453 return UPNP_E_SUCCESS;
1454}
1455#endif /* COMPA_HAVE_CTRLPT_SSDP */
1456
1457#ifdef COMPA_HAVE_CTRLPT_SSDP
1459 struct Handle_Info* HInfo;
1460 ListNode* node = NULL;
1461 SsdpSearchArg* searchArg = NULL;
1462
1463 if (UpnpSdkInit != 1)
1464 return UPNP_E_FINISH;
1465 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1466 "Inside UpnpUnRegisterClient \n");
1467
1468 HandleLock();
1470 HandleUnlock();
1471 return UPNP_E_INVALID_HANDLE;
1472 }
1473 HandleUnlock();
1474
1475#ifdef COMPA_HAVE_CTRLPT_GENA
1477 return UPNP_E_INVALID_HANDLE;
1478#endif
1479 HandleLock();
1480 switch (GetHandleInfo(Hnd, &HInfo)) {
1481 case HND_INVALID:
1482 HandleUnlock();
1483 return UPNP_E_INVALID_HANDLE;
1484 default:
1485 break;
1486 }
1487 /* clean up search list */
1488 node = ListHead(&HInfo->SsdpSearchList);
1489 while (node != NULL) {
1490 searchArg = (SsdpSearchArg*)node->item;
1491 if (searchArg) {
1492 free(searchArg->searchTarget);
1493 free(searchArg);
1494 }
1495 ListDelNode(&HInfo->SsdpSearchList, node, 0);
1496 node = ListHead(&HInfo->SsdpSearchList);
1497 }
1498 ListDestroy(&HInfo->SsdpSearchList, 0);
1499 FreeHandle(Hnd);
1501 HandleUnlock();
1502
1503 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1504 "Exiting UpnpUnRegisterClient \n");
1505
1506 return UPNP_E_SUCCESS;
1507}
1508#endif /* COMPA_HAVE_CTRLPT_SSDP */
1509
1510#ifdef COMPA_HAVE_DEVICE_DESCRIPTION
1518 char* name,
1520 char** alias) {
1521 char* ext;
1522 char* al;
1523
1524 ext = strrchr(name, '.');
1525 if (ext == NULL || strcasecmp(ext, ".xml") != 0) {
1526 return UPNP_E_EXT_NOT_XML;
1527 }
1528
1529 al = strrchr(name, '/');
1530 if (al == NULL) {
1531 *alias = name;
1532 } else {
1533 *alias = al;
1534 }
1535
1536 return UPNP_E_SUCCESS;
1537}
1538
1544 struct sockaddr* serverAddr) {
1545 struct sockaddr_in* sa4 = (struct sockaddr_in*)serverAddr;
1546
1547 memset(serverAddr, 0, sizeof(struct sockaddr_storage));
1548
1549 sa4->sin_family = AF_INET;
1550 inet_pton(AF_INET, gIF_IPV4, &sa4->sin_addr);
1551 sa4->sin_port = htons(LOCAL_PORT_V4);
1552}
1553
1559 struct sockaddr* serverAddr) {
1560 struct sockaddr_in6* sa6 = (struct sockaddr_in6*)serverAddr;
1561
1562 memset(serverAddr, 0, sizeof(struct sockaddr_storage));
1563
1564 sa6->sin6_family = AF_INET6;
1565 inet_pton(AF_INET6, gIF_IPV6, &sa6->sin6_addr);
1566 sa6->sin6_port = htons(LOCAL_PORT_V6);
1567}
1568
1569static int GetDescDocumentAndURL(Upnp_DescType descriptionType,
1570 char* description, int config_baseURL,
1571 int AddressFamily, IXML_Document** xmlDoc,
1572 char descURL[LINE_SIZE]) {
1573 int retVal = 0;
1574 char* membuf = NULL;
1575 char aliasStr[LINE_SIZE];
1576 char* temp_str = NULL;
1577 FILE* fp = NULL;
1578 int fd;
1579 size_t fileLen;
1580 size_t num_read;
1581 time_t last_modified{};
1582 struct stat file_info;
1583 struct sockaddr_storage serverAddr;
1584 int rc = UPNP_E_SUCCESS;
1585
1586 memset(aliasStr, 0, sizeof(aliasStr));
1587 if (description == NULL)
1588 return UPNP_E_INVALID_PARAM;
1589 /* non-URL description must have configuration specified */
1590 if (descriptionType != (enum Upnp_DescType_e)UPNPREG_URL_DESC &&
1591 !config_baseURL)
1592 return UPNP_E_INVALID_PARAM;
1593 /* Get XML doc and last modified time */
1594 if (descriptionType == (enum Upnp_DescType_e)UPNPREG_URL_DESC) {
1595 retVal = UpnpDownloadXmlDoc(description, xmlDoc);
1596 if (retVal != UPNP_E_SUCCESS)
1597 return retVal;
1598 last_modified = time(NULL);
1599 } else if (descriptionType == (enum Upnp_DescType_e)UPNPREG_FILENAME_DESC) {
1600 int ret = 0;
1601
1602#ifdef _WIN32
1603 umock::stdio_h.fopen_s(&fp, description, "rb");
1604#else
1605 fp = umock::stdio_h.fopen(description, "rb");
1606#endif
1607 if (!fp) {
1609 ret = 1;
1610 goto exit_function1;
1611 }
1612 fd = fileno(fp);
1613 if (fd == -1) {
1615 ret = 1;
1616 goto exit_function1;
1617 }
1618 retVal = fstat(fd, &file_info);
1619 if (retVal == -1) {
1621 ret = 1;
1622 goto exit_function1;
1623 }
1624 fileLen = (size_t)file_info.st_size;
1625 last_modified = file_info.st_mtime;
1626 membuf = (char*)malloc(fileLen + (size_t)1);
1627 if (!membuf) {
1629 ret = 1;
1630 goto exit_function1;
1631 }
1632 num_read = umock::stdio_h.fread(membuf, (size_t)1, fileLen, fp);
1633 if (num_read != fileLen) {
1635 ret = 1;
1636 goto exit_function2;
1637 }
1638 membuf[fileLen] = 0;
1639 rc = ixmlParseBufferEx(membuf, xmlDoc);
1640 exit_function2:
1641 if (membuf) {
1642 free(membuf);
1643 }
1644 exit_function1:
1645 if (fp) {
1646 umock::stdio_h.fclose(fp);
1647 }
1648 if (ret) {
1649 return rc;
1650 }
1651 } else if (descriptionType == (enum Upnp_DescType_e)UPNPREG_BUF_DESC) {
1652 last_modified = time(NULL);
1653 rc = ixmlParseBufferEx(description, xmlDoc);
1654 } else {
1655 return UPNP_E_INVALID_PARAM;
1656 }
1657
1658 if (rc != IXML_SUCCESS &&
1659 descriptionType != (enum Upnp_DescType_e)UPNPREG_URL_DESC) {
1660 if (rc == IXML_INSUFFICIENT_MEMORY)
1661 return UPNP_E_OUTOF_MEMORY;
1662 else
1663 return UPNP_E_INVALID_DESC;
1664 }
1665 /* Determine alias */
1666 if (config_baseURL) {
1667 if (descriptionType == (enum Upnp_DescType_e)UPNPREG_BUF_DESC) {
1668 strncpy(aliasStr, "description.xml", sizeof(aliasStr) - 1);
1669 } else {
1670 /* URL or filename */
1671 retVal = GetNameForAlias(description, &temp_str);
1672 if (retVal != UPNP_E_SUCCESS) {
1673 ixmlDocument_free(*xmlDoc);
1674 return retVal;
1675 }
1676 if (strlen(temp_str) > (LINE_SIZE - 1)) {
1677 ixmlDocument_free(*xmlDoc);
1678 return UPNP_E_URL_TOO_BIG;
1679 }
1680 strncpy(aliasStr, temp_str, sizeof(aliasStr) - 1);
1681 }
1682 if (AddressFamily == AF_INET) {
1683 get_server_addr((struct sockaddr*)&serverAddr);
1684 } else {
1685 get_server_addr6((struct sockaddr*)&serverAddr);
1686 }
1687
1688 /* config */
1689 retVal = configure_urlbase(*xmlDoc, (struct sockaddr*)&serverAddr,
1690 aliasStr, last_modified, descURL);
1691 if (retVal != UPNP_E_SUCCESS) {
1692 ixmlDocument_free(*xmlDoc);
1693 return retVal;
1694 }
1695 } else {
1696 /* Manual */
1697 if (strlen(description) > LINE_SIZE - 1) {
1698 ixmlDocument_free(*xmlDoc);
1699 return UPNP_E_URL_TOO_BIG;
1700 }
1701 strncpy(descURL, description, LINE_SIZE - 1);
1702 descURL[LINE_SIZE - 1] = '\0';
1703 }
1704
1705 assert(*xmlDoc != NULL);
1706
1707 return UPNP_E_SUCCESS;
1708}
1709#endif // COMPA_HAVE_DEVICE_DESCRIPTION
1710
1711/*******************************************************************************
1712 *
1713 * SSDP interface
1714 *
1715 ******************************************************************************/
1716
1717#ifdef COMPA_HAVE_DEVICE_SSDP
1719 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1720 "Inside UpnpSendAdvertisement \n");
1721 return UpnpSendAdvertisementLowPower(Hnd, Exp, -1, -1, -1);
1722}
1723
1725 int PowerState, int SleepPeriod,
1726 int RegistrationState) {
1727 struct Handle_Info* SInfo = NULL;
1728 int retVal = 0, *ptrMx;
1729 job_arg* adEvent;
1730 ThreadPoolJob job;
1731
1732 memset(&job, 0, sizeof(job));
1733
1734 if (UpnpSdkInit != 1) {
1735 return UPNP_E_FINISH;
1736 }
1737
1738 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1739 "Inside UpnpSendAdvertisementLowPower \n");
1740
1741 HandleLock();
1742 switch (GetHandleInfo(Hnd, &SInfo)) {
1743 case HND_DEVICE:
1744 break;
1745 default:
1746 HandleUnlock();
1747 return UPNP_E_INVALID_HANDLE;
1748 }
1749 if (Exp < 1)
1750 Exp = DEFAULT_MAXAGE;
1751 if (Exp <= AUTO_ADVERTISEMENT_TIME * 2)
1752 Exp = (AUTO_ADVERTISEMENT_TIME + 1) * 2;
1753 SInfo->MaxAge = Exp;
1754 SInfo->PowerState = PowerState;
1755 if (SleepPeriod < 0)
1756 SleepPeriod = -1;
1757 SInfo->SleepPeriod = SleepPeriod;
1759 HandleUnlock();
1760 retVal = AdvertiseAndReply(1, Hnd, (enum SsdpSearchType)0,
1761 (struct sockaddr*)NULL, (char*)NULL, (char*)NULL,
1762 (char*)NULL, Exp);
1763
1764 if (retVal != UPNP_E_SUCCESS)
1765 return retVal;
1766 ptrMx = (int*)malloc(sizeof(int));
1767 if (ptrMx == NULL)
1768 return UPNP_E_OUTOF_MEMORY;
1769 adEvent = (job_arg*)malloc(sizeof(job_arg));
1770
1771 if (adEvent == NULL) {
1772 free(ptrMx);
1773 return UPNP_E_OUTOF_MEMORY;
1774 }
1775 *ptrMx = Exp;
1776 adEvent->advertise.handle = Hnd;
1777 adEvent->advertise.Event = ptrMx;
1778
1779 HandleLock();
1780 switch (GetHandleInfo(Hnd, &SInfo)) {
1781 case HND_DEVICE:
1782 break;
1783 default:
1784 HandleUnlock();
1785 free(adEvent);
1786 free(ptrMx);
1787 return UPNP_E_INVALID_HANDLE;
1788 }
1789#ifdef SSDP_PACKET_DISTRIBUTE
1790 TPJobInit(&job, (UPnPsdk::start_routine)AutoAdvertise, adEvent);
1792 TPJobSetPriority(&job, MED_PRIORITY);
1793 if ((retVal = TimerThreadSchedule(
1794 &gTimerThread, ((Exp / 2) - (AUTO_ADVERTISEMENT_TIME)), REL_SEC,
1795 &job, SHORT_TERM, &(adEvent->advertise.eventId))) !=
1797 HandleUnlock();
1798 free_advertise_arg(adEvent);
1799 return retVal;
1800 }
1801#else
1802 TPJobInit(&job, (UPnPsdk::start_routine)AutoAdvertise, adEvent);
1804 TPJobSetPriority(&job, MED_PRIORITY);
1805 if ((retVal = TimerThreadSchedule(
1807 SHORT_TERM, &(adEvent->advertise.eventId))) != UPNP_E_SUCCESS) {
1808 HandleUnlock();
1809 free_advertise_arg(adEvent);
1810 return retVal;
1811 }
1812#endif
1813
1814 HandleUnlock();
1815 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1816 "Exiting UpnpSendAdvertisementLowPower \n");
1817
1818 return retVal;
1819}
1820#endif /* COMPA_HAVE_DEVICE_SSDP */
1821
1822#ifdef COMPA_HAVE_CTRLPT_SSDP
1823int UpnpSearchAsync(UpnpClient_Handle Hnd, int Mx, const char* Target_const,
1824 const void* Cookie_const) {
1825 struct Handle_Info* SInfo = NULL;
1826 char* Target = (char*)Target_const;
1827 int retVal;
1828
1829 if (UpnpSdkInit != 1) {
1830 return UPNP_E_FINISH;
1831 }
1832
1833 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSearchAsync\n");
1834
1836 switch (GetHandleInfo(Hnd, &SInfo)) {
1837 case HND_CLIENT:
1838 break;
1839 default:
1840 HandleUnlock();
1841 return UPNP_E_INVALID_HANDLE;
1842 }
1843 if (Mx < 1)
1844 Mx = DEFAULT_MX;
1845
1846 if (Target == NULL) {
1847 HandleUnlock();
1848 return UPNP_E_INVALID_PARAM;
1849 }
1850
1851 HandleUnlock();
1852 retVal = SearchByTarget(Hnd, Mx, Target, (void*)Cookie_const);
1853 if (retVal != 1)
1854 return retVal;
1855
1856 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSearchAsync \n");
1857
1858 return UPNP_E_SUCCESS;
1859}
1860#endif /* COMPA_HAVE_CTRLPT_SSDP */
1861
1862/*******************************************************************************
1863 *
1864 * GENA interface
1865 *
1866 ******************************************************************************/
1867
1868#ifdef COMPA_HAVE_DEVICE_GENA
1870 struct Handle_Info* SInfo = NULL;
1871
1872 if (UpnpSdkInit != 1) {
1873 return UPNP_E_FINISH;
1874 }
1875
1876 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1877 "Inside UpnpSetMaxSubscriptions \n");
1878
1879 HandleLock();
1880 switch (GetHandleInfo(Hnd, &SInfo)) {
1881 case HND_DEVICE:
1882 break;
1883 default:
1884 HandleUnlock();
1885 return UPNP_E_INVALID_HANDLE;
1886 }
1888 HandleUnlock();
1889 return UPNP_E_INVALID_HANDLE;
1890 }
1892 HandleUnlock();
1893
1894 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1895 "Exiting UpnpSetMaxSubscriptions \n");
1896
1897 return UPNP_E_SUCCESS;
1898}
1899#endif /* COMPA_HAVE_DEVICE_GENA */
1900
1901#ifdef COMPA_HAVE_DEVICE_GENA
1904 struct Handle_Info* SInfo = NULL;
1905
1906 if (UpnpSdkInit != 1) {
1907 return UPNP_E_FINISH;
1908 }
1909
1910 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1911 "Inside UpnpSetMaxSubscriptionTimeOut\n");
1912
1913 HandleLock();
1914
1915 switch (GetHandleInfo(Hnd, &SInfo)) {
1916 case HND_DEVICE:
1917 break;
1918 default:
1919 HandleUnlock();
1920 return UPNP_E_INVALID_HANDLE;
1921 }
1923 (MaxSubscriptionTimeOut < 0)) {
1924 HandleUnlock();
1925 return UPNP_E_INVALID_HANDLE;
1926 }
1927
1929 HandleUnlock();
1930
1931 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1932 "Exiting UpnpSetMaxSubscriptionTimeOut\n");
1933
1934 return UPNP_E_SUCCESS;
1935}
1936#endif /* COMPA_HAVE_DEVICE_GENA */
1937
1938#ifdef COMPA_HAVE_CTRLPT_GENA
1939int UpnpSubscribeAsync(UpnpClient_Handle Hnd, const char* EvtUrl_const,
1940 int TimeOut, Upnp_FunPtr Fun, const void* Cookie_const) {
1941 struct Handle_Info* SInfo = NULL;
1942 struct UpnpNonblockParam* Param;
1943 char* EvtUrl = (char*)EvtUrl_const;
1944 ThreadPoolJob job;
1945
1946 memset(&job, 0, sizeof(job));
1947
1948 if (UpnpSdkInit != 1) {
1949 return UPNP_E_FINISH;
1950 }
1951
1952 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1953 "Inside UpnpSubscribeAsync\n");
1954
1956 switch (GetHandleInfo(Hnd, &SInfo)) {
1957 case HND_CLIENT:
1958 break;
1959 default:
1960 HandleUnlock();
1961 return UPNP_E_INVALID_HANDLE;
1962 }
1963 if (EvtUrl == NULL) {
1964 HandleUnlock();
1965 return UPNP_E_INVALID_PARAM;
1966 }
1967 if (TimeOut != UPNP_INFINITE && TimeOut < 1) {
1968 HandleUnlock();
1969 return UPNP_E_INVALID_PARAM;
1970 }
1971 if (Fun == NULL) {
1972 HandleUnlock();
1973 return UPNP_E_INVALID_PARAM;
1974 }
1975 HandleUnlock();
1976
1977 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
1978 if (Param == NULL) {
1979 return UPNP_E_OUTOF_MEMORY;
1980 }
1981 memset(Param, 0, sizeof(struct UpnpNonblockParam));
1982
1983 Param->FunName = SUBSCRIBE;
1984 Param->Handle = Hnd;
1985 strncpy(Param->Url, EvtUrl, sizeof(Param->Url) - 1);
1986 Param->TimeOut = TimeOut;
1987 Param->Fun = Fun;
1988 Param->Cookie = (char*)Cookie_const;
1989
1990 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
1992 TPJobSetPriority(&job, MED_PRIORITY);
1993 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
1994 free(Param);
1995 }
1996
1997 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
1998 "Exiting UpnpSubscribeAsync\n");
1999
2000 return UPNP_E_SUCCESS;
2001}
2002#endif /* COMPA_HAVE_CTRLPT_GENA */
2003
2004#ifdef COMPA_HAVE_CTRLPT_GENA
2005int UpnpSubscribe(UpnpClient_Handle Hnd, const char* EvtUrl_const, int* TimeOut,
2006 Upnp_SID SubsId) {
2007 int retVal;
2008 struct Handle_Info* SInfo = NULL;
2009 UpnpString* EvtUrl = UpnpString_new();
2010 UpnpString* SubsIdTmp = UpnpString_new();
2011
2012 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSubscribe\n");
2013
2014 if (UpnpSdkInit != 1) {
2015 retVal = UPNP_E_FINISH;
2016 goto exit_function;
2017 }
2018
2019 if (EvtUrl == NULL) {
2020 retVal = UPNP_E_OUTOF_MEMORY;
2021 goto exit_function;
2022 }
2023 if (EvtUrl_const == NULL) {
2024 retVal = UPNP_E_INVALID_PARAM;
2025 goto exit_function;
2026 }
2027 UpnpString_set_String(EvtUrl, EvtUrl_const);
2028
2029 if (SubsIdTmp == NULL) {
2030 retVal = UPNP_E_OUTOF_MEMORY;
2031 goto exit_function;
2032 }
2033 if (SubsId == NULL) {
2034 retVal = UPNP_E_INVALID_PARAM;
2035 goto exit_function;
2036 }
2037 UpnpString_set_String(SubsIdTmp, SubsId);
2038
2039 if (TimeOut == NULL) {
2040 retVal = UPNP_E_INVALID_PARAM;
2041 goto exit_function;
2042 }
2043
2045 switch (GetHandleInfo(Hnd, &SInfo)) {
2046 case HND_CLIENT:
2047 break;
2048 default:
2049 HandleUnlock();
2050 retVal = UPNP_E_INVALID_HANDLE;
2051 goto exit_function;
2052 }
2053 HandleUnlock();
2054
2055 retVal = genaSubscribe(Hnd, EvtUrl, TimeOut, SubsIdTmp);
2056 memset(SubsId, 0, sizeof(Upnp_SID));
2057 strncpy(SubsId, UpnpString_get_String(SubsIdTmp), sizeof(Upnp_SID) - 1);
2058
2059exit_function:
2060 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2061 "Exiting UpnpSubscribe, retVal=%d\n", retVal);
2062
2063 UpnpString_delete(SubsIdTmp);
2064 UpnpString_delete(EvtUrl);
2065
2066 return retVal;
2067}
2068#endif /* COMPA_HAVE_CTRLPT_GENA */
2069
2070#ifdef COMPA_HAVE_CTRLPT_GENA
2072 struct Handle_Info* SInfo = NULL;
2073 int retVal;
2074 UpnpString* SubsIdTmp = UpnpString_new();
2075
2076 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpUnSubscribe\n");
2077
2078 if (UpnpSdkInit != 1) {
2079 retVal = UPNP_E_FINISH;
2080 goto exit_function;
2081 }
2082
2083 if (SubsIdTmp == NULL) {
2084 retVal = UPNP_E_OUTOF_MEMORY;
2085 goto exit_function;
2086 }
2087 if (SubsId == NULL) {
2088 retVal = UPNP_E_INVALID_PARAM;
2089 goto exit_function;
2090 }
2091 UpnpString_set_String(SubsIdTmp, SubsId);
2092
2094 switch (GetHandleInfo(Hnd, &SInfo)) {
2095 case HND_CLIENT:
2096 break;
2097 default:
2098 HandleUnlock();
2099 retVal = UPNP_E_INVALID_HANDLE;
2100 goto exit_function;
2101 }
2102 HandleUnlock();
2103
2104 retVal = genaUnSubscribe(Hnd, SubsIdTmp);
2105
2106exit_function:
2107 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2108 "Exiting UpnpUnSubscribe, retVal=%d\n", retVal);
2109
2110 UpnpString_delete(SubsIdTmp);
2111
2112 return retVal;
2113}
2114#endif /* COMPA_HAVE_CTRLPT_GENA */
2115
2116#ifdef COMPA_HAVE_CTRLPT_GENA
2118 Upnp_FunPtr Fun, const void* Cookie_const) {
2119 int retVal = UPNP_E_SUCCESS;
2120 ThreadPoolJob job;
2121 struct Handle_Info* SInfo = NULL;
2122 struct UpnpNonblockParam* Param;
2123
2124 memset(&job, 0, sizeof(job));
2125
2126 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2127 "Inside UpnpUnSubscribeAsync\n");
2128
2129 if (UpnpSdkInit != 1) {
2130 retVal = UPNP_E_FINISH;
2131 goto exit_function;
2132 }
2133
2134 if (SubsId == NULL) {
2135 retVal = UPNP_E_INVALID_PARAM;
2136 goto exit_function;
2137 }
2138 if (Fun == NULL) {
2139 retVal = UPNP_E_INVALID_PARAM;
2140 goto exit_function;
2141 }
2142
2144 switch (GetHandleInfo(Hnd, &SInfo)) {
2145 case HND_CLIENT:
2146 break;
2147 default:
2148 HandleUnlock();
2149 retVal = UPNP_E_INVALID_HANDLE;
2150 goto exit_function;
2151 }
2152 HandleUnlock();
2153
2154 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2155 if (Param == NULL) {
2156 retVal = UPNP_E_OUTOF_MEMORY;
2157 goto exit_function;
2158 }
2159 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2160
2161 Param->FunName = UNSUBSCRIBE;
2162 Param->Handle = Hnd;
2163 strncpy(Param->SubsId, SubsId, sizeof(Param->SubsId) - 1);
2164 Param->Fun = Fun;
2165 Param->Cookie = (char*)Cookie_const;
2166 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2168 TPJobSetPriority(&job, MED_PRIORITY);
2169 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2170 free(Param);
2171 }
2172
2173exit_function:
2174 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2175 "Exiting UpnpUnSubscribeAsync\n");
2176
2177 return retVal;
2178}
2179#endif /* COMPA_HAVE_CTRLPT_GENA */
2180
2181#ifdef COMPA_HAVE_CTRLPT_GENA
2183 const Upnp_SID SubsId) {
2184 struct Handle_Info* SInfo = NULL;
2185 int retVal;
2186 UpnpString* SubsIdTmp = UpnpString_new();
2187
2188 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2189 "Inside UpnpRenewSubscription\n");
2190
2191 if (UpnpSdkInit != 1) {
2192 retVal = UPNP_E_FINISH;
2193 goto exit_function;
2194 }
2195
2196 if (SubsIdTmp == NULL) {
2197 retVal = UPNP_E_OUTOF_MEMORY;
2198 goto exit_function;
2199 }
2200 if (SubsId == NULL) {
2201 retVal = UPNP_E_INVALID_PARAM;
2202 goto exit_function;
2203 }
2204 UpnpString_set_String(SubsIdTmp, SubsId);
2205
2206 if (TimeOut == NULL) {
2207 retVal = UPNP_E_INVALID_PARAM;
2208 goto exit_function;
2209 }
2210
2212 switch (GetHandleInfo(Hnd, &SInfo)) {
2213 case HND_CLIENT:
2214 break;
2215 default:
2216 HandleUnlock();
2217 retVal = UPNP_E_INVALID_HANDLE;
2218 goto exit_function;
2219 }
2220 HandleUnlock();
2221
2222 retVal = genaRenewSubscription(Hnd, SubsIdTmp, TimeOut);
2223
2224exit_function:
2225 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2226 "Exiting UpnpRenewSubscription, retVal=%d\n", retVal);
2227
2228 UpnpString_delete(SubsIdTmp);
2229
2230 return retVal;
2231}
2232#endif /* COMPA_HAVE_CTRLPT_GENA */
2233
2234#ifdef COMPA_HAVE_CTRLPT_GENA
2236 Upnp_SID SubsId, Upnp_FunPtr Fun,
2237 const void* Cookie_const) {
2238 ThreadPoolJob job;
2239 struct Handle_Info* SInfo = NULL;
2240 struct UpnpNonblockParam* Param;
2241
2242 memset(&job, 0, sizeof(job));
2243
2244 if (UpnpSdkInit != 1) {
2245 return UPNP_E_FINISH;
2246 }
2247
2248 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2249 "Inside UpnpRenewSubscriptionAsync\n");
2251 switch (GetHandleInfo(Hnd, &SInfo)) {
2252 case HND_CLIENT:
2253 break;
2254 default:
2255 HandleUnlock();
2256 return UPNP_E_INVALID_HANDLE;
2257 }
2258 if (TimeOut != UPNP_INFINITE && TimeOut < 1) {
2259 HandleUnlock();
2260 return UPNP_E_INVALID_PARAM;
2261 }
2262 if (SubsId == NULL) {
2263 HandleUnlock();
2264 return UPNP_E_INVALID_PARAM;
2265 }
2266 if (Fun == NULL) {
2267 HandleUnlock();
2268 return UPNP_E_INVALID_PARAM;
2269 }
2270 HandleUnlock();
2271
2272 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2273 if (Param == NULL) {
2274 return UPNP_E_OUTOF_MEMORY;
2275 }
2276 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2277
2278 Param->FunName = RENEW;
2279 Param->Handle = Hnd;
2280 strncpy(Param->SubsId, SubsId, sizeof(Param->SubsId) - 1);
2281 Param->Fun = Fun;
2282 Param->Cookie = (char*)Cookie_const;
2283 Param->TimeOut = TimeOut;
2284
2285 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2287 TPJobSetPriority(&job, MED_PRIORITY);
2288 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2289 free(Param);
2290 }
2291
2292 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2293 "Exiting UpnpRenewSubscriptionAsync\n");
2294
2295 return UPNP_E_SUCCESS;
2296}
2297#endif /* COMPA_HAVE_CTRLPT_GENA */
2298
2299#ifdef COMPA_HAVE_DEVICE_GENA
2300int UpnpNotify(UpnpDevice_Handle Hnd, const char* DevID_const,
2301 const char* ServName_const, const char** VarName_const,
2302 const char** NewVal_const, int cVariables) {
2303 struct Handle_Info* SInfo = NULL;
2304 int retVal;
2305 char* DevID = (char*)DevID_const;
2306 char* ServName = (char*)ServName_const;
2307 char** VarName = (char**)VarName_const;
2308 char** NewVal = (char**)NewVal_const;
2309
2310 if (UpnpSdkInit != 1) {
2311 return UPNP_E_FINISH;
2312 }
2313
2314 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpNotify\n");
2315
2317 switch (GetHandleInfo(Hnd, &SInfo)) {
2318 case HND_DEVICE:
2319 break;
2320 default:
2321 HandleUnlock();
2322 return UPNP_E_INVALID_HANDLE;
2323 }
2324 if (DevID == NULL) {
2325 HandleUnlock();
2326 return UPNP_E_INVALID_PARAM;
2327 }
2328 if (ServName == NULL) {
2329 HandleUnlock();
2330 return UPNP_E_INVALID_PARAM;
2331 }
2332 if (VarName == NULL || NewVal == NULL || cVariables < 0) {
2333 HandleUnlock();
2334 return UPNP_E_INVALID_PARAM;
2335 }
2336
2337 HandleUnlock();
2338 retVal = genaNotifyAll(Hnd, DevID, ServName, VarName, NewVal, cVariables);
2339
2340 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpNotify\n");
2341
2342 return retVal;
2343}
2344
2345int UpnpNotifyExt(UpnpDevice_Handle Hnd, const char* DevID_const,
2346 const char* ServName_const, IXML_Document* PropSet) {
2347 struct Handle_Info* SInfo = NULL;
2348 int retVal;
2349 char* DevID = (char*)DevID_const;
2350 char* ServName = (char*)ServName_const;
2351
2352 if (UpnpSdkInit != 1) {
2353 return UPNP_E_FINISH;
2354 }
2355
2356 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpNotify \n");
2357
2359 switch (GetHandleInfo(Hnd, &SInfo)) {
2360 case HND_DEVICE:
2361 break;
2362 default:
2363 HandleUnlock();
2364 return UPNP_E_INVALID_HANDLE;
2365 }
2366 if (DevID == NULL) {
2367 HandleUnlock();
2368 return UPNP_E_INVALID_PARAM;
2369 }
2370 if (ServName == NULL) {
2371 HandleUnlock();
2372 return UPNP_E_INVALID_PARAM;
2373 }
2374
2375 HandleUnlock();
2376 retVal = genaNotifyAllExt(Hnd, DevID, ServName, PropSet);
2377
2378 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpNotify \n");
2379
2380 return retVal;
2381}
2382#endif /* COMPA_HAVE_DEVICE_GENA */
2383
2384#ifdef COMPA_HAVE_DEVICE_GENA
2385int UpnpAcceptSubscription(UpnpDevice_Handle Hnd, const char* DevID_const,
2386 const char* ServName_const,
2387 const char** VarName_const,
2388 const char** NewVal_const, int cVariables,
2389 const Upnp_SID SubsId) {
2390 int ret = 0;
2391 int line = 0;
2392 struct Handle_Info* SInfo = NULL;
2393 char* DevID = (char*)DevID_const;
2394 char* ServName = (char*)ServName_const;
2395 char** VarName = (char**)VarName_const;
2396 char** NewVal = (char**)NewVal_const;
2397
2398 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2399 "Inside UpnpAcceptSubscription\n");
2400
2401 if (UpnpSdkInit != 1) {
2402 line = __LINE__;
2403 ret = UPNP_E_FINISH;
2404 goto exit_function;
2405 }
2406
2408
2409 switch (GetHandleInfo(Hnd, &SInfo)) {
2410 case HND_DEVICE:
2411 break;
2412 default:
2413 HandleUnlock();
2414 line = __LINE__;
2416 goto exit_function;
2417 }
2418 if (DevID == NULL) {
2419 HandleUnlock();
2420 line = __LINE__;
2422 goto exit_function;
2423 }
2424 if (ServName == NULL) {
2425 HandleUnlock();
2426 line = __LINE__;
2428 goto exit_function;
2429 }
2430 if (SubsId == NULL) {
2431 HandleUnlock();
2432 line = __LINE__;
2434 goto exit_function;
2435 }
2436/* Now accepts an empty state list, so the code below is
2437 * commented out */
2438#if 0
2439 if (VarName == NULL || NewVal == NULL || cVariables < 0) {
2440 HandleUnlock();
2441 line = __LINE__;
2443 goto exit_function;
2444 }
2445#endif
2446
2447 HandleUnlock();
2448
2449 line = __LINE__;
2450 ret = genaInitNotify(Hnd, DevID, ServName, VarName, NewVal, cVariables,
2451 SubsId);
2452
2453exit_function:
2454 UpnpPrintf(UPNP_ALL, API, __FILE__, line,
2455 "Exiting UpnpAcceptSubscription, ret = %d\n", ret);
2456
2457 return ret;
2458}
2459
2460int UpnpAcceptSubscriptionExt(UpnpDevice_Handle Hnd, const char* DevID_const,
2461 const char* ServName_const,
2462 IXML_Document* PropSet, const Upnp_SID SubsId) {
2463 int ret = 0;
2464 int line = 0;
2465 struct Handle_Info* SInfo = NULL;
2466 char* DevID = (char*)DevID_const;
2467 char* ServName = (char*)ServName_const;
2468
2469 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2470 "Inside UpnpAcceptSubscription\n");
2471
2472 if (UpnpSdkInit != 1) {
2473 line = __LINE__;
2474 ret = UPNP_E_FINISH;
2475 goto exit_function;
2476 }
2477
2479
2480 switch (GetHandleInfo(Hnd, &SInfo)) {
2481 case HND_DEVICE:
2482 break;
2483 default:
2484 HandleUnlock();
2485 line = __LINE__;
2487 goto exit_function;
2488 }
2489 if (DevID == NULL) {
2490 HandleUnlock();
2491 line = __LINE__;
2493 goto exit_function;
2494 }
2495 if (ServName == NULL) {
2496 HandleUnlock();
2497 line = __LINE__;
2499 goto exit_function;
2500 }
2501 if (SubsId == NULL) {
2502 HandleUnlock();
2503 line = __LINE__;
2505 goto exit_function;
2506 }
2507/* Now accepts an empty state list, so the code below is
2508 * commented out */
2509#if 0
2510 if (PropSet == NULL) {
2511 HandleUnlock();
2512 line = __LINE__;
2514 goto exit_function;
2515 }
2516#endif
2517
2518 HandleUnlock();
2519
2520 line = __LINE__;
2521 ret = genaInitNotifyExt(Hnd, DevID, ServName, PropSet, SubsId);
2522
2523exit_function:
2524 UpnpPrintf(UPNP_ALL, API, __FILE__, line,
2525 "Exiting UpnpAcceptSubscription, ret = %d.\n", ret);
2526
2527 return ret;
2528}
2529#endif /* COMPA_HAVE_DEVICE_GENA */
2530
2531/*******************************************************************************
2532 *
2533 * SOAP interface
2534 *
2535 ******************************************************************************/
2536
2537#ifdef COMPA_HAVE_CTRLPT_SOAP
2538int UpnpSendAction(UpnpClient_Handle Hnd, const char* ActionURL_const,
2539 const char* ServiceType_const, const char* DevUDN_const,
2540 IXML_Document* Action, IXML_Document** RespNodePtr) {
2541 struct Handle_Info* SInfo = NULL;
2542 int retVal = 0;
2543 char* ActionURL = (char*)ActionURL_const;
2544 char* ServiceType = (char*)ServiceType_const;
2545 /* udn not used? */
2546 /*char *DevUDN = (char *)DevUDN_const;*/
2547
2548 if (UpnpSdkInit != 1) {
2549 return UPNP_E_FINISH;
2550 }
2551
2552 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSendAction\n");
2553 if (DevUDN_const != NULL) {
2554 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2555 "non NULL DevUDN is ignored\n");
2556 }
2557 DevUDN_const = NULL;
2558
2560 switch (GetHandleInfo(Hnd, &SInfo)) {
2561 case HND_CLIENT:
2562 break;
2563 default:
2564 HandleUnlock();
2565 return UPNP_E_INVALID_HANDLE;
2566 }
2567 HandleUnlock();
2568
2569 if (ActionURL == NULL) {
2570 return UPNP_E_INVALID_PARAM;
2571 }
2572
2573 if (ServiceType == NULL || Action == NULL || RespNodePtr == NULL ||
2574 DevUDN_const != NULL) {
2575
2576 return UPNP_E_INVALID_PARAM;
2577 }
2578
2579 retVal = SoapSendAction(ActionURL, ServiceType, Action, RespNodePtr);
2580
2581 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSendAction\n");
2582
2583 return retVal;
2584}
2585
2586int UpnpSendActionEx(UpnpClient_Handle Hnd, const char* ActionURL_const,
2587 const char* ServiceType_const, const char* DevUDN_const,
2588 IXML_Document* Header, IXML_Document* Action,
2589 IXML_Document** RespNodePtr) {
2590 struct Handle_Info* SInfo = NULL;
2591 int retVal = 0;
2592 char* ActionURL = (char*)ActionURL_const;
2593 char* ServiceType = (char*)ServiceType_const;
2594 /* udn not used? */
2595 /*char *DevUDN = (char *)DevUDN_const;*/
2596
2597 if (UpnpSdkInit != 1) {
2598 return UPNP_E_FINISH;
2599 }
2600
2601 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Inside UpnpSendActionEx\n");
2602
2603 if (Header == NULL) {
2604 retVal = UpnpSendAction(Hnd, ActionURL_const, ServiceType_const,
2605 DevUDN_const, Action, RespNodePtr);
2606 return retVal;
2607 }
2608
2610 switch (GetHandleInfo(Hnd, &SInfo)) {
2611 case HND_CLIENT:
2612 break;
2613 default:
2614 HandleUnlock();
2615 return UPNP_E_INVALID_HANDLE;
2616 }
2617 HandleUnlock();
2618
2619 if (ActionURL == NULL) {
2620 return UPNP_E_INVALID_PARAM;
2621 }
2622 if (ServiceType == NULL || Action == NULL || RespNodePtr == NULL) {
2623 return UPNP_E_INVALID_PARAM;
2624 }
2625
2626 retVal =
2627 SoapSendActionEx(ActionURL, ServiceType, Header, Action, RespNodePtr);
2628
2629 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "Exiting UpnpSendAction \n");
2630
2631 return retVal;
2632}
2633
2634int UpnpSendActionAsync(UpnpClient_Handle Hnd, const char* ActionURL_const,
2635 const char* ServiceType_const, const char* DevUDN_const,
2636 IXML_Document* Act, Upnp_FunPtr Fun,
2637 const void* Cookie_const) {
2638 int rc;
2639 ThreadPoolJob job;
2640 struct Handle_Info* SInfo = NULL;
2641 struct UpnpNonblockParam* Param;
2642 DOMString tmpStr;
2643 char* ActionURL = (char*)ActionURL_const;
2644 char* ServiceType = (char*)ServiceType_const;
2645 /* udn not used? */
2646 /*char *DevUDN = (char *)DevUDN_const;*/
2647
2648 memset(&job, 0, sizeof(job));
2649
2650 if (UpnpSdkInit != 1) {
2651 return UPNP_E_FINISH;
2652 }
2653
2654 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2655 "Inside UpnpSendActionAsync\n");
2656
2658 switch (GetHandleInfo(Hnd, &SInfo)) {
2659 case HND_CLIENT:
2660 break;
2661 default:
2662 HandleUnlock();
2663 return UPNP_E_INVALID_HANDLE;
2664 }
2665 HandleUnlock();
2666
2667 if (ActionURL == NULL) {
2668 return UPNP_E_INVALID_PARAM;
2669 }
2670 if (ServiceType == NULL || Act == NULL || Fun == NULL ||
2671 DevUDN_const != NULL) {
2672 return UPNP_E_INVALID_PARAM;
2673 }
2674 tmpStr = ixmlPrintNode((IXML_Node*)Act);
2675 if (tmpStr == NULL) {
2676 return UPNP_E_INVALID_ACTION;
2677 }
2678
2679 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2680
2681 if (Param == NULL) {
2682 ixmlFreeDOMString(tmpStr);
2683 return UPNP_E_OUTOF_MEMORY;
2684 }
2685 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2686
2687 Param->FunName = ACTION;
2688 Param->Handle = Hnd;
2689 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2690 strncpy(Param->ServiceType, ServiceType, sizeof(Param->ServiceType) - 1);
2691
2692 rc = ixmlParseBufferEx(tmpStr, &(Param->Act));
2693 if (rc != IXML_SUCCESS) {
2694 free(Param);
2695 ixmlFreeDOMString(tmpStr);
2696 if (rc == IXML_INSUFFICIENT_MEMORY) {
2697 return UPNP_E_OUTOF_MEMORY;
2698 } else {
2699 return UPNP_E_INVALID_ACTION;
2700 }
2701 }
2702 ixmlFreeDOMString(tmpStr);
2703 Param->Cookie = (char*)Cookie_const;
2704 Param->Fun = Fun;
2705
2706 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2708
2709 TPJobSetPriority(&job, MED_PRIORITY);
2710 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2711 free_action_arg((job_arg*)Param);
2712 }
2713
2714 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2715 "Exiting UpnpSendActionAsync \n");
2716
2717 return UPNP_E_SUCCESS;
2718}
2719
2720int UpnpSendActionExAsync(UpnpClient_Handle Hnd, const char* ActionURL_const,
2721 const char* ServiceType_const,
2722 const char* DevUDN_const, IXML_Document* Header,
2724 const void* Cookie_const) {
2725 struct Handle_Info* SInfo = NULL;
2726 struct UpnpNonblockParam* Param;
2727 DOMString tmpStr;
2728 DOMString headerStr = NULL;
2729 char* ActionURL = (char*)ActionURL_const;
2730 char* ServiceType = (char*)ServiceType_const;
2731 ThreadPoolJob job;
2732 int retVal = 0;
2733
2734 memset(&job, 0, sizeof(job));
2735
2736 if (UpnpSdkInit != 1) {
2737 return UPNP_E_FINISH;
2738 }
2739
2740 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2741 "Inside UpnpSendActionExAsync\n");
2742
2743 if (Header == NULL) {
2744 retVal = UpnpSendActionAsync(Hnd, ActionURL_const, ServiceType_const,
2745 DevUDN_const, Act, Fun, Cookie_const);
2746 return retVal;
2747 }
2748
2750 switch (GetHandleInfo(Hnd, &SInfo)) {
2751 case HND_CLIENT:
2752 break;
2753 default:
2754 HandleUnlock();
2755 return UPNP_E_INVALID_HANDLE;
2756 }
2757 HandleUnlock();
2758
2759 if (ActionURL == NULL) {
2760 return UPNP_E_INVALID_PARAM;
2761 }
2762 if (ServiceType == NULL || Act == NULL || Fun == NULL) {
2763 return UPNP_E_INVALID_PARAM;
2764 }
2765
2766 headerStr = ixmlPrintNode((IXML_Node*)Header);
2767
2768 tmpStr = ixmlPrintNode((IXML_Node*)Act);
2769 if (tmpStr == NULL) {
2770 ixmlFreeDOMString(headerStr);
2771 return UPNP_E_INVALID_ACTION;
2772 }
2773
2774 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2775 if (Param == NULL) {
2776 ixmlFreeDOMString(tmpStr);
2777 ixmlFreeDOMString(headerStr);
2778 return UPNP_E_OUTOF_MEMORY;
2779 }
2780 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2781
2782 Param->FunName = ACTION;
2783 Param->Handle = Hnd;
2784 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2785 strncpy(Param->ServiceType, ServiceType, sizeof(Param->ServiceType) - 1);
2786 retVal = ixmlParseBufferEx(headerStr, &(Param->Header));
2787 if (retVal != IXML_SUCCESS) {
2788 free(Param);
2789 ixmlFreeDOMString(tmpStr);
2790 ixmlFreeDOMString(headerStr);
2791 if (retVal == IXML_INSUFFICIENT_MEMORY) {
2792 return UPNP_E_OUTOF_MEMORY;
2793 } else {
2794 return UPNP_E_INVALID_ACTION;
2795 }
2796 }
2797
2798 retVal = ixmlParseBufferEx(tmpStr, &(Param->Act));
2799 if (retVal != IXML_SUCCESS) {
2800 ixmlDocument_free(Param->Header);
2801 free(Param);
2802 ixmlFreeDOMString(tmpStr);
2803 ixmlFreeDOMString(headerStr);
2804 if (retVal == IXML_INSUFFICIENT_MEMORY) {
2805 return UPNP_E_OUTOF_MEMORY;
2806 } else {
2807 return UPNP_E_INVALID_ACTION;
2808 }
2809 }
2810
2811 ixmlFreeDOMString(tmpStr);
2812 ixmlFreeDOMString(headerStr);
2813
2814 Param->Cookie = (char*)Cookie_const;
2815 Param->Fun = Fun;
2816
2817 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2819
2820 TPJobSetPriority(&job, MED_PRIORITY);
2821 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2822 free_action_arg((job_arg*)Param);
2823 }
2824
2825 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2826 "Exiting UpnpSendActionAsync\n");
2827
2828 return UPNP_E_SUCCESS;
2829}
2830
2831// Deprecated
2833 const char* ActionURL_const,
2834 const char* VarName_const, Upnp_FunPtr Fun,
2835 const void* Cookie_const) {
2836 ThreadPoolJob job;
2837 struct Handle_Info* SInfo = NULL;
2838 struct UpnpNonblockParam* Param;
2839 char* ActionURL = (char*)ActionURL_const;
2840 char* VarName = (char*)VarName_const;
2841
2842 memset(&job, 0, sizeof(job));
2843
2844 if (UpnpSdkInit != 1) {
2845 return UPNP_E_FINISH;
2846 }
2847
2848 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2849 "Inside UpnpGetServiceVarStatusAsync\n");
2850
2852 switch (GetHandleInfo(Hnd, &SInfo)) {
2853 case HND_CLIENT:
2854 break;
2855 default:
2856 HandleUnlock();
2857 return UPNP_E_INVALID_HANDLE;
2858 }
2859 HandleUnlock();
2860
2861 if (ActionURL == NULL) {
2862 return UPNP_E_INVALID_PARAM;
2863 }
2864 if (VarName == NULL || Fun == NULL)
2865 return UPNP_E_INVALID_PARAM;
2866
2867 Param = (struct UpnpNonblockParam*)malloc(sizeof(struct UpnpNonblockParam));
2868 if (Param == NULL) {
2869 return UPNP_E_OUTOF_MEMORY;
2870 }
2871 memset(Param, 0, sizeof(struct UpnpNonblockParam));
2872
2873 Param->FunName = STATUS;
2874 Param->Handle = Hnd;
2875 strncpy(Param->Url, ActionURL, sizeof(Param->Url) - 1);
2876 strncpy(Param->VarName, VarName, sizeof(Param->VarName) - 1);
2877 Param->Fun = Fun;
2878 Param->Cookie = (char*)Cookie_const;
2879
2880 TPJobInit(&job, (UPnPsdk::start_routine)UpnpThreadDistribution, Param);
2882
2883 TPJobSetPriority(&job, MED_PRIORITY);
2884
2885 if (ThreadPoolAdd(&gSendThreadPool, &job, NULL) != 0) {
2886 free(Param);
2887 }
2888
2889 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2890 "Exiting UpnpGetServiceVarStatusAsync\n");
2891
2892 return UPNP_E_SUCCESS;
2893}
2894
2895// Deprecated
2896int UpnpGetServiceVarStatus(UpnpClient_Handle Hnd, const char* ActionURL_const,
2897 const char* VarName_const, DOMString* StVar) {
2898 struct Handle_Info* SInfo = NULL;
2899 int retVal = 0;
2900 char* StVarPtr;
2901 char* ActionURL = (char*)ActionURL_const;
2902 char* VarName = (char*)VarName_const;
2903
2904 if (UpnpSdkInit != 1) {
2905 return UPNP_E_FINISH;
2906 }
2907
2908 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2909 "Inside UpnpGetServiceVarStatus\n");
2910
2912 switch (GetHandleInfo(Hnd, &SInfo)) {
2913 case HND_CLIENT:
2914 break;
2915 default:
2916 HandleUnlock();
2917 return UPNP_E_INVALID_HANDLE;
2918 }
2919
2920 HandleUnlock();
2921
2922 if (ActionURL == NULL) {
2923 return UPNP_E_INVALID_PARAM;
2924 }
2925 if (VarName == NULL || StVar == NULL) {
2926 return UPNP_E_INVALID_PARAM;
2927 }
2928
2929 retVal = SoapGetServiceVarStatus(ActionURL, VarName, &StVarPtr);
2930 *StVar = StVarPtr;
2931
2932 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
2933 "Exiting UpnpGetServiceVarStatus \n");
2934
2935 return retVal;
2936}
2937#endif /* COMPA_HAVE_CTRLPT_SOAP */
2938
2939/*******************************************************************************
2940 *
2941 * Client API
2942 *
2943 ******************************************************************************/
2944#ifdef COMPA_HAVE_WEBSERVER
2945int UpnpOpenHttpPost(const char* url, void** handle, const char* contentType,
2946 int contentLength, int timeout) {
2947 int status = http_OpenHttpConnection(url, handle, timeout);
2948 if (status == UPNP_E_SUCCESS) {
2949 return http_MakeHttpRequest(UPNP_HTTPMETHOD_POST, url, handle, NULL,
2950 contentType, contentLength, timeout);
2951 }
2952 return status;
2953}
2954
2955int UpnpWriteHttpPost(void* handle, char* buf, size_t* size, int timeout) {
2956 return http_WriteHttpRequest(handle, buf, size, timeout);
2957}
2958
2959int UpnpCloseHttpPost(void* handle, int* httpStatus, int timeout) {
2960 int status = http_EndHttpRequest(handle, timeout);
2961 if (status == UPNP_E_SUCCESS) {
2962 /* status = */ http_GetHttpResponse(handle, NULL, NULL, NULL,
2963 httpStatus, timeout);
2964 }
2965 status = http_CloseHttpConnection(handle);
2966 return status;
2967}
2968
2969int UpnpOpenHttpGet(const char* url, void** handle, char** contentType,
2970 int* contentLength, int* httpStatus, int timeout) {
2971 int status = UpnpOpenHttpConnection(url, handle, timeout);
2972 if (status == UPNP_E_SUCCESS) {
2973 status = UpnpMakeHttpRequest(UPNP_HTTPMETHOD_GET, url, *handle, NULL,
2974 NULL, 0, timeout);
2975 }
2976 if (status == UPNP_E_SUCCESS) {
2977 status = UpnpEndHttpRequest(*handle, timeout);
2978 }
2979 if (status == UPNP_E_SUCCESS) {
2980 status = UpnpGetHttpResponse(*handle, NULL, contentType, contentLength,
2981 httpStatus, timeout);
2982 }
2983 return status;
2984}
2985
2986int UpnpOpenHttpGetProxy(const char* url, const char* proxy_str, void** handle,
2987 char** contentType, int* contentLength,
2988 int* httpStatus, int timeout) {
2989 int status = UpnpOpenHttpConnection(proxy_str, handle, timeout);
2990 if (status == UPNP_E_SUCCESS) {
2991 status = UpnpMakeHttpRequest(UPNP_HTTPMETHOD_GET, url, *handle, NULL,
2992 NULL, 0, timeout);
2993 }
2994 if (status == UPNP_E_SUCCESS) {
2995 status = UpnpEndHttpRequest(*handle, timeout);
2996 }
2997 if (status == UPNP_E_SUCCESS) {
2998 status = UpnpGetHttpResponse(*handle, NULL, contentType, contentLength,
2999 httpStatus, timeout);
3000 }
3001 return status;
3002}
3003
3004int UpnpOpenHttpGetEx(const char* url_str, void** Handle, char** contentType,
3005 int* contentLength, int* httpStatus, int lowRange,
3006 int highRange, int timeout) {
3007 return http_OpenHttpGetEx(url_str, Handle, contentType, contentLength,
3008 httpStatus, lowRange, highRange, timeout);
3009}
3010
3011int UpnpCancelHttpGet(void* Handle) { return http_CancelHttpGet(Handle); }
3012
3013int UpnpCloseHttpGet(void* Handle) { return UpnpCloseHttpConnection(Handle); }
3014
3015int UpnpReadHttpGet(void* Handle, char* buf, size_t* size, int timeout) {
3016 return http_ReadHttpResponse(Handle, buf, size, timeout);
3017}
3018
3019int UpnpHttpGetProgress(void* Handle, size_t* length, size_t* total) {
3020 return http_HttpGetProgress(Handle, length, total);
3021}
3022
3023int UpnpOpenHttpConnection(const char* url, void** handle, int timeout) {
3024 return http_OpenHttpConnection(url, handle, timeout);
3025}
3026
3027int UpnpMakeHttpRequest(Upnp_HttpMethod method, const char* url, void* handle,
3028 UpnpString* headers, const char* contentType,
3029 int contentLength, int timeout) {
3030 return http_MakeHttpRequest(method, url, handle, headers, contentType,
3031 contentLength, timeout);
3032}
3033
3034int UpnpWriteHttpRequest(void* handle, char* buf, size_t* size, int timeout) {
3035 return http_WriteHttpRequest(handle, buf, size, timeout);
3036}
3037
3038int UpnpEndHttpRequest(void* handle, int timeout) {
3039 return http_EndHttpRequest(handle, timeout);
3040}
3041
3042int UpnpGetHttpResponse(void* handle, UpnpString* headers, char** contentType,
3043 int* contentLength, int* httpStatus, int timeout) {
3044 return http_GetHttpResponse(handle, headers, contentType, contentLength,
3045 httpStatus, timeout);
3046}
3047
3048int UpnpReadHttpResponse(void* handle, char* buf, size_t* size, int timeout) {
3049 return http_ReadHttpResponse(handle, buf, size, timeout);
3050}
3051
3052int UpnpCloseHttpConnection(void* handle) {
3053 return http_CloseHttpConnection(handle);
3054}
3055#endif // COMPA_HAVE_WEBSERVER
3056
3057#ifdef COMPA_HAVE_WEBSERVER
3058int UpnpDownloadUrlItem(const char* url, char** outBuf, char* contentType) {
3059 int ret_code;
3060 size_t doc_length;
3061
3062 if (url == nullptr || outBuf == nullptr || contentType == nullptr)
3063 return UPNP_E_INVALID_PARAM;
3064 ret_code = http_Download(url, HTTP_DEFAULT_TIMEOUT, outBuf, &doc_length,
3065 contentType);
3066 if (ret_code > 0)
3067 /* error reply was received */
3068 ret_code = UPNP_E_INVALID_URL;
3069
3070 return ret_code;
3071}
3072#else
3073int UpnpDownloadUrlItem([[maybe_unused]] const char* url,
3074 [[maybe_unused]] char** outBuf,
3075 [[maybe_unused]] char* contentType) {
3076 return UPNP_E_INVALID_PARAM;
3077}
3078#endif
3079
3080int UpnpDownloadXmlDoc(const char* url, IXML_Document** xmlDoc) {
3081 TRACE("Executing UpnpDownloadXmlDoc()")
3082 if (url == nullptr || xmlDoc == nullptr) {
3083 return UPNP_E_INVALID_PARAM;
3084 }
3085
3086 char* xml_buf;
3087 char content_type[LINE_SIZE];
3088 int ret_code = UpnpDownloadUrlItem(url, &xml_buf, content_type);
3089 if (ret_code != UPNP_E_SUCCESS) {
3090 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3091 "Error downloading document, retCode: %d\n", ret_code);
3092 return ret_code;
3093 }
3094
3095 if (strncasecmp(content_type, "text/xml", strlen("text/xml"))) {
3096 UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, "Not text/xml\n");
3097 /* Linksys WRT54G router returns
3098 * "CONTENT-TYPE: application/octet-stream".
3099 * Let's be nice to Linksys and try to parse document anyway.
3100 * If the data sended is not a xml file, ixmlParseBufferEx
3101 * will fail and the function will return UPNP_E_INVALID_DESC
3102 * too. */
3103#if 0
3104 free(xml_buf);
3105 return UPNP_E_INVALID_DESC;
3106#endif
3107 }
3108
3109 ret_code = ixmlParseBufferEx(xml_buf, xmlDoc);
3110 free(xml_buf);
3111 if (ret_code != IXML_SUCCESS) {
3112 if (ret_code == IXML_INSUFFICIENT_MEMORY) {
3113 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3114 "Out of memory, ixml error code: %d\n", ret_code);
3115 return UPNP_E_OUTOF_MEMORY;
3116 } else {
3117 UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
3118 "Invalid Description, ixml error code: %d\n", ret_code);
3119 return UPNP_E_INVALID_DESC;
3120 }
3121 } else {
3122#ifdef DEBUG
3123 xml_buf = ixmlPrintNode((IXML_Node*)*xmlDoc);
3124 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3125 "Printing the Parsed xml document \n %s\n", xml_buf);
3126 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3127 "****************** END OF Parsed XML Doc "
3128 "*****************\n");
3129 ixmlFreeDOMString(xml_buf);
3130#endif
3131 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3132 "Exiting UpnpDownloadXmlDoc\n");
3133
3134 return UPNP_E_SUCCESS;
3135 }
3136}
3137
3141#if defined(COMPA_HAVE_CTRLPT_SOAP) || defined(COMPA_HAVE_CTRLPT_GENA)
3143 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3144 "Inside UpnpThreadDistribution \n");
3145
3146 switch (Param->FunName) {
3147#ifdef COMPA_HAVE_CTRLPT_GENA
3148 case SUBSCRIBE: {
3150 UpnpString* Sid = UpnpString_new();
3151
3153 int errCode = genaSubscribe(Param->Handle,
3155 (int*)&Param->TimeOut, Sid);
3156 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3159 Param->Fun(UPNP_EVENT_SUBSCRIBE_COMPLETE, evt, Param->Cookie);
3160 UpnpString_delete(Sid);
3162 free(Param);
3163 break;
3164 }
3165 case UNSUBSCRIBE: {
3168 int errCode =
3170 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3173 Param->Fun(UPNP_EVENT_UNSUBSCRIBE_COMPLETE, evt, Param->Cookie);
3175 free(Param);
3176 break;
3177 }
3178 case RENEW: {
3181 int errCode = genaRenewSubscription(
3182 Param->Handle, UpnpEventSubscribe_get_SID(evt), &Param->TimeOut);
3183 UpnpEventSubscribe_set_ErrCode(evt, errCode);
3185 Param->Fun(UPNP_EVENT_RENEWAL_COMPLETE, evt, Param->Cookie);
3187 free(Param);
3188 break;
3189 }
3190#endif /* COMPA_HAVE_CTRLPT_GENA */
3191#ifdef COMPA_HAVE_CTRLPT_SOAP
3192 case ACTION: {
3194 IXML_Document* actionResult = NULL;
3195 int errCode;
3196 if (Param->Header) {
3197 errCode =
3198 SoapSendActionEx(Param->Url, Param->ServiceType, Param->Header,
3199 Param->Act, &actionResult);
3200 } else {
3201 errCode = SoapSendAction(Param->Url, Param->ServiceType, Param->Act,
3202 &actionResult);
3203 }
3204 UpnpActionComplete_set_ErrCode(Evt, errCode);
3206 UpnpActionComplete_set_ActionResult(Evt, actionResult);
3208 Param->Fun(UPNP_CONTROL_ACTION_COMPLETE, Evt, Param->Cookie);
3210 ixmlDocument_free(actionResult);
3211 free_action_arg((job_arg*)Param);
3212 break;
3213 }
3214 case STATUS: {
3216 DOMString currentVal = NULL;
3217 int errCode =
3218 SoapGetServiceVarStatus(Param->Url, Param->VarName, &currentVal);
3222 UpnpStateVarComplete_set_CurrentVal(Evt, currentVal);
3223 Param->Fun(UPNP_CONTROL_GET_VAR_COMPLETE, Evt, Param->Cookie);
3224 free(Param);
3226 break;
3227 }
3228#endif /* COMPA_HAVE_CTRLPT_SOAP */
3229 default:
3230 break;
3231 }
3232
3233 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3234 "Exiting UpnpThreadDistribution\n");
3235}
3236#endif /* COMPA_HAVE_CTRLPT_SOAP || COMPA_HAVE_CTRLPT_GENA */
3237
3244 return ((struct Handle_Info*)compa::HandleTable[Hnd])->Callback;
3245}
3246
3247/* Assumes at most one client */
3249 struct Handle_Info** HndInfo) {
3250 UpnpClient_Handle client;
3251
3252 for (client = 1; client < NUM_HANDLE; client++) {
3253 switch (GetHandleInfo(client, HndInfo)) {
3254 case HND_TABLE_INVALID:
3255 goto exit_loop;
3256 case HND_CLIENT:
3257 *client_handle_out = client;
3258 return HND_CLIENT;
3259 default:;
3260 }
3261 }
3262exit_loop:
3263 *client_handle_out = -1;
3264 return HND_INVALID;
3265}
3266
3269 [[maybe_unused]] int AddressFamily,
3270 UpnpDevice_Handle* device_handle_out,
3271 [[maybe_unused]] struct Handle_Info** HndInfo) {
3272#ifdef COMPA_HAVE_DEVICE_SSDP
3273 /* Check if we've got a registered device of the address family
3274 * specified. */
3275 if ((AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 0) ||
3276 (AddressFamily == AF_INET6 && UpnpSdkDeviceregisteredV6 == 0)) {
3277 *device_handle_out = -1;
3278 return HND_INVALID;
3279 }
3280 if (start < 0 || start >= NUM_HANDLE - 1) {
3281 *device_handle_out = -1;
3282 return HND_INVALID;
3283 }
3284 ++start;
3285 /* Find it. */
3286 for (*device_handle_out = start; *device_handle_out < NUM_HANDLE;
3287 (*device_handle_out)++) {
3288 switch (GetHandleInfo(*device_handle_out, HndInfo)) {
3289 case HND_DEVICE:
3290 if ((*HndInfo)->DeviceAf == AddressFamily) {
3291 return HND_DEVICE;
3292 }
3293 break;
3294 default:
3295 break;
3296 }
3297 }
3298#endif /* COMPA_HAVE_DEVICE_SSDP */
3299
3300 *device_handle_out = -1;
3301 return HND_INVALID;
3302}
3303
3305GetDeviceHandleInfoForPath([[maybe_unused]] const char* path,
3306 [[maybe_unused]] int AddressFamily,
3307 UpnpDevice_Handle* device_handle_out,
3308 [[maybe_unused]] struct Handle_Info** HndInfo,
3309 [[maybe_unused]] service_info** serv_info) {
3310#ifdef COMPA_HAVE_DEVICE_SSDP
3311 /* Check if we've got a registered device of the address family
3312 * specified. */
3313 if ((AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 0) ||
3314 (AddressFamily == AF_INET6 && UpnpSdkDeviceregisteredV6 == 0)) {
3315 *device_handle_out = -1;
3316 return HND_INVALID;
3317 }
3318 /* Find it. */
3319 for (*device_handle_out = 1; *device_handle_out < NUM_HANDLE;
3320 (*device_handle_out)++) {
3321 switch (GetHandleInfo(*device_handle_out, HndInfo)) {
3322 case HND_DEVICE:
3323 if ((*HndInfo)->DeviceAf == AddressFamily) {
3324 if (((*serv_info = FindServiceControlURLPath(
3325 &(*HndInfo)->ServiceTable, path)) != 0) ||
3326 ((*serv_info = FindServiceEventURLPath(
3327 &(*HndInfo)->ServiceTable, path)) != 0)) {
3328 return HND_DEVICE;
3329 }
3330 }
3331 break;
3332 default:
3333 break;
3334 }
3335 }
3336#endif /* COMPA_HAVE_DEVICE_SSDP */
3337
3338 *device_handle_out = -1;
3339 return HND_INVALID;
3340}
3341
3343 // This function expects an initialized global compa::HandleTable HndInfo,
3344 // at least with nullptr.
3345 Upnp_Handle_Type ret{HND_TABLE_INVALID};
3346
3347 if (HndInfo == nullptr) {
3348 UPnPsdk_LOGERR("MSG1097") "No output variable for handle info "
3349 "available (HndInfo==nullptr).\n";
3350 } else if (Hnd < 1 || Hnd >= NUM_HANDLE) {
3351 UPnPsdk_LOGERR("MSG1130") "Handle(" << Hnd << ") out of range.\n";
3352 ret = HND_INVALID;
3353 } else if (compa::HandleTable[Hnd] == nullptr) {
3354 // When scanning the whole handle info table we have a lot of empty
3355 // entries. That seems not to be an error.
3356 ret = HND_INVALID;
3357 } else {
3358 *HndInfo = compa::HandleTable[Hnd];
3359 ret = (*HndInfo)->HType;
3360 }
3361 return ret;
3362}
3363
3365 struct Handle_Info* HndInfo;
3366 if (compa::HandleTable[Hnd] != nullptr) {
3367 HndInfo = compa::HandleTable[Hnd];
3368 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
3369 "Printing information for Handle_%d\n", Hnd);
3370 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "HType_%d\n",
3371 HndInfo->HType);
3372#ifdef COMPA_HAVE_DEVICE_SSDP
3373 switch (HndInfo->HType) {
3374 case HND_CLIENT:
3375 break;
3376 default:
3377 UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, "DescURL_%s\n",
3378 HndInfo->DescURL);
3379 }
3380#endif
3381 } else {
3382 return UPNP_E_INVALID_HANDLE;
3383 }
3384
3385 return UPNP_E_SUCCESS;
3386}
3387
3388#ifdef COMPA_HAVE_DEVICE_SSDP
3389void AutoAdvertise(void* input) {
3390 job_arg* arg = (job_arg*)input;
3391
3392 UpnpSendAdvertisement(arg->advertise.handle, *((int*)arg->advertise.Event));
3393 free_advertise_arg(arg);
3394}
3395#endif
3396
3397#ifdef COMPA_HAVE_WEBSERVER
3398int UpnpSetWebServerRootDir(const char* rootDir) {
3399 TRACE("Executing UpnpSetWebServerRootDir()")
3400 if (UpnpSdkInit == 0)
3401 return UPNP_E_FINISH;
3402 if ((rootDir == nullptr) || (strlen(rootDir) == 0)) {
3403 return UPNP_E_INVALID_PARAM;
3404 }
3405
3407
3408 return web_server_set_root_dir(rootDir);
3409}
3410
3411int UpnpSetWebServerCorsString(const char* corsString) {
3412 if (UpnpSdkInit == 0)
3413 return UPNP_E_FINISH;
3414 if ((corsString == NULL) || (strlen(corsString) == 0)) {
3415 return UPNP_E_INVALID_PARAM;
3416 }
3417
3419
3420 return web_server_set_cors(corsString);
3421}
3422#endif /* COMPA_HAVE_WEBSERVER */
3423
3424int UpnpAddVirtualDir(const char* newDirName, const void* cookie,
3425 const void** oldcookie) {
3426 virtualDirList* pNewVirtualDir;
3427 virtualDirList* pLast;
3428 virtualDirList* pCurVirtualDir;
3429 char dirName[NAME_SIZE];
3430
3431 memset(dirName, 0, sizeof(dirName));
3432 if (UpnpSdkInit != 1) {
3433 /* SDK is not initialized */
3434 return UPNP_E_FINISH;
3435 }
3436
3437 if ((newDirName == NULL) || (strlen(newDirName) == (size_t)0)) {
3438 return UPNP_E_INVALID_PARAM;
3439 }
3440
3441 if (*newDirName != '/') {
3442 if (strlen(newDirName) > sizeof(dirName) - 2)
3443 return UPNP_E_INVALID_PARAM;
3444 dirName[0] = '/';
3445 strncpy(dirName + 1, newDirName, sizeof(dirName) - 2);
3446 } else {
3447 if (strlen(newDirName) > sizeof(dirName) - 1)
3448 return UPNP_E_INVALID_PARAM;
3449 strncpy(dirName, newDirName, sizeof(dirName) - 1);
3450 }
3451
3452 pCurVirtualDir = pVirtualDirList;
3453 while (pCurVirtualDir != NULL) {
3454 /* already has this entry */
3455 if (strcmp(pCurVirtualDir->dirName, dirName) == 0) {
3456 if (oldcookie != NULL)
3457 *oldcookie = pCurVirtualDir->cookie;
3458 pCurVirtualDir->cookie = cookie;
3459 return UPNP_E_SUCCESS;
3460 }
3461
3462 pCurVirtualDir = pCurVirtualDir->next;
3463 }
3464
3465 pNewVirtualDir = (virtualDirList*)malloc(sizeof(virtualDirList));
3466 if (pNewVirtualDir == NULL) {
3467 return UPNP_E_OUTOF_MEMORY;
3468 }
3469 pNewVirtualDir->next = NULL;
3470 if (oldcookie != NULL)
3471 *oldcookie = NULL;
3472 pNewVirtualDir->cookie = cookie;
3473 memset(pNewVirtualDir->dirName, 0, sizeof(pNewVirtualDir->dirName));
3474#ifdef UPNPLIB_PUPNP_BUG
3475 // Error if compiling old code with build type Release: output may be
3476 // truncated copying 255 bytes from a string of length 255
3477 // [-Werror=stringop-truncation]. We have to fix it here otherwise it won't
3478 // compile. --Ingo
3479 strncpy(pNewVirtualDir->dirName, dirName,
3480 sizeof(pNewVirtualDir->dirName) - 1);
3481#else
3482 strncpy(pNewVirtualDir->dirName, dirName, sizeof(pNewVirtualDir->dirName));
3483#endif
3484 *(pNewVirtualDir->dirName + strlen(dirName)) = 0;
3485
3486 if (pVirtualDirList == NULL) { /* first virtual dir */
3487 pVirtualDirList = pNewVirtualDir;
3488 } else {
3489 pLast = pVirtualDirList;
3490 while (pLast->next != NULL) {
3491 pLast = pLast->next;
3492 }
3493 pLast->next = pNewVirtualDir;
3494 }
3495
3496 return UPNP_E_SUCCESS;
3497}
3498
3499int UpnpRemoveVirtualDir(const char* dirName) {
3500 virtualDirList* pPrev;
3501 virtualDirList* pCur;
3502 int found = 0;
3503
3504 if (UpnpSdkInit != 1) {
3505 return UPNP_E_FINISH;
3506 }
3507
3508 if (dirName == NULL) {
3509 return UPNP_E_INVALID_PARAM;
3510 }
3511
3512 if (pVirtualDirList == NULL) {
3513 return UPNP_E_INVALID_PARAM;
3514 }
3515 /* Handle the special case where the directory that we are */
3516 /* removing is the first in the list. */
3517 if (strcmp(pVirtualDirList->dirName, dirName) == 0) {
3518 pPrev = pVirtualDirList;
3520 free(pPrev);
3521 return UPNP_E_SUCCESS;
3522 }
3523
3524 pCur = pVirtualDirList->next;
3525 pPrev = pVirtualDirList;
3526
3527 while (pCur != NULL) {
3528 if (strcmp(pCur->dirName, dirName) == 0) {
3529 pPrev->next = pCur->next;
3530 free(pCur);
3531 found = 1;
3532 break;
3533 } else {
3534 pPrev = pCur;
3535 pCur = pCur->next;
3536 }
3537 }
3538
3539 if (found == 1)
3540 return UPNP_E_SUCCESS;
3541 else
3542 return UPNP_E_INVALID_PARAM;
3543}
3544
3546 virtualDirList* pCur;
3547 virtualDirList* pNext;
3548
3549 if (UpnpSdkInit != 1) {
3550 return;
3551 }
3552
3553 pCur = pVirtualDirList;
3554
3555 while (pCur != NULL) {
3556 pNext = pCur->next;
3557 free(pCur);
3558
3559 pCur = pNext;
3560 }
3561
3562 pVirtualDirList = NULL;
3563}
3564
3565int UpnpEnableWebserver([[maybe_unused]] int enable) {
3566 TRACE("Executing UpnpEnableWebserver()")
3567 if (UpnpSdkInit != 1) {
3568 return UPNP_E_FINISH;
3569 }
3570#ifdef COMPA_HAVE_WEBSERVER
3571 if (enable)
3573 else
3575 return UPNP_E_SUCCESS;
3576#else /* Internal web server disabled */
3577 return UPNP_E_NO_WEB_SERVER;
3578#endif /* COMPA_HAVE_WEBSERVER */
3579}
3580
3582 if (UpnpSdkInit != 1) {
3583 return 0;
3584 }
3585
3586 return bWebServerState == (WebServerState)WEB_SERVER_ENABLED;
3587}
3588
3590 void* cookie) {
3591 gWebCallback_HostValidate = callback;
3593}
3594
3598
3600 int ret = UPNP_E_SUCCESS;
3601 if (!callback) {
3603 } else {
3604 virtualDirCallback.get_info = callback;
3605 }
3606
3607 return ret;
3608}
3609
3611 int ret = UPNP_E_SUCCESS;
3612 if (!callback) {
3614 } else {
3615 virtualDirCallback.open = callback;
3616 }
3617
3618 return ret;
3619}
3620
3622 int ret = UPNP_E_SUCCESS;
3623 if (!callback) {
3625 } else {
3626 virtualDirCallback.read = callback;
3627 }
3628
3629 return ret;
3630}
3631
3633 int ret = UPNP_E_SUCCESS;
3634 if (!callback) {
3636 } else {
3637 virtualDirCallback.write = callback;
3638 }
3639
3640 return ret;
3641}
3642
3644 int ret = UPNP_E_SUCCESS;
3645 if (!callback) {
3647 } else {
3648 virtualDirCallback.seek = callback;
3649 }
3650
3651 return ret;
3652}
3653
3655 int ret = UPNP_E_SUCCESS;
3656 if (!callback) {
3658 } else {
3659 virtualDirCallback.close = callback;
3660 }
3661
3662 return ret;
3663}
3664
3665// Deprecated
3666int UpnpSetContentLength(UpnpClient_Handle Hnd, size_t contentLength) {
3667 int errCode = UPNP_E_SUCCESS;
3668 struct Handle_Info* HInfo = NULL;
3669
3670 do {
3671 if (UpnpSdkInit != 1) {
3672 errCode = UPNP_E_FINISH;
3673 break;
3674 }
3675
3676 HandleLock();
3677
3678 switch (GetHandleInfo(Hnd, &HInfo)) {
3679 case HND_DEVICE:
3680 break;
3681 default:
3682 HandleUnlock();
3683 return UPNP_E_INVALID_HANDLE;
3684 }
3685 if (contentLength > MAX_SOAP_CONTENT_LENGTH) {
3686 errCode = UPNP_E_OUTOF_BOUNDS;
3687 break;
3688 }
3689 g_maxContentLength = contentLength;
3690 } while (0);
3691
3692 HandleUnlock();
3693 return errCode;
3694}
3695
3696int UpnpSetMaxContentLength(size_t contentLength) {
3697 int errCode = UPNP_E_SUCCESS;
3698
3699 do {
3700 if (UpnpSdkInit != 1) {
3701 errCode = UPNP_E_FINISH;
3702 break;
3703 }
3704 g_maxContentLength = contentLength;
3705 } while (0);
3706
3707 return errCode;
3708}
@ 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:434
#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:468
@ UPNPREG_FILENAME_DESC
Definition API.hpp:474
@ UPNPREG_BUF_DESC
Definition API.hpp:478
@ UPNPREG_URL_DESC
Definition API.hpp:470
#define UPNP_E_OUTOF_BOUNDS
The operation completed successfully.
Definition API.hpp:355
#define NAME_SIZE
Definition API.hpp:46
int UpnpClient_Handle
Returned when a control point application registers with UpnpRegisterClient().
Definition API.hpp:415
#define UPNP_INFINITE
Definition API.hpp:51
int UpnpDevice_Handle
Returned when a device application registers with UpnpRegisterRootDevice(),UpnpRegisterRootDevice2(),...
Definition API.hpp:425
#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:481
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.
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.
#define HTTP_DEFAULT_TIMEOUT
membuffer gDocumentRootDir
Definition webserver.hpp:45
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 socknetmask(SSockaddr &a_snetmask) const
Get socket address netmask from current selected list 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:385
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:377
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:338
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:390
#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:452
PUPNP_Api void ixmlFreeDOMString(DOMString buf)
Frees a DOMString.
Definition ixml.cpp:418
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:47
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:1311
int UpnpInit2(const char *IfName, unsigned short DestPort)
Initializes the Linux SDK for UPnP Devices.
Definition upnpapi.cpp:594
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:2896
Upnp_HttpMethod
Different HTTP methods.
Definition API.hpp:1945
PUPNP_Api int UpnpDownloadXmlDoc(const char *url, IXML_Document **xmlDoc)
Downloads an XML document specified in a URL.
Definition upnpapi.cpp:3080
@ UPNP_HTTPMETHOD_GET
GET.
Definition API.hpp:1948
@ UPNP_HTTPMETHOD_POST
POST.
Definition API.hpp:1950
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:1823
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:2385
int(* VDCallback_Close)(UpnpWebFileHandle fileHnd, const void *cookie, const void *request_cookie)
Close callback function prototype.
Definition API.hpp:2746
int(* VDCallback_GetInfo)(const char *filename, UpnpFileInfo *info, const void *cookie, const void **request_cookie)
Get-info callback function prototype.
Definition API.hpp:2592
int(* WebCallback_HostValidate)(const char *hostname, void *cookie)
Callback for validating HTTP requests HOST header values.
Definition API.hpp:2800
int(* VDCallback_Seek)(UpnpWebFileHandle fileHnd, off_t offset, int origin, const void *cookie, const void *request_cookie)
Seek callback function prototype.
Definition API.hpp:2715
int(* VDCallback_Write)(UpnpWebFileHandle fileHnd, char *buf, size_t buflen, const void *cookie, const void *request_cookie)
Write callback function prototype.
Definition API.hpp:2689
int(* VDCallback_Read)(UpnpWebFileHandle fileHnd, char *buf, size_t buflen, const void *cookie, const void *request_cookie)
Read callback function prototype.
Definition API.hpp:2663
UpnpWebFileHandle(* VDCallback_Open)(const char *filename, enum UpnpOpenFileMode Mode, const void *cookie, const void *request_cookie)
Open callback function prototype.
Definition API.hpp:2638
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 UpnpGetIfInfo(std::string_view a_iface="")
Retrieve local network adapter information and keep it in global variables.
Definition upnpapi.cpp:120
pthread_mutex_t sdkInit_mutex
Initialization mutex.
Definition upnpapi.cpp:89
Handle_Info * HandleTable[NUM_HANDLE]
UPnP Device and Control Point handle table
Definition upnpapi.cpp:92
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:94
sockaddr_in6 & sin6
Reference to sockaddr_in6 struct.
Definition sockaddr.hpp:100
const std::string netaddr() noexcept
Get the assosiated netaddress without port.
Definition sockaddr.cpp:469
sockaddr_storage & ss
Reference to sockaddr_storage struct.
Definition sockaddr.hpp:96
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:2634
WebCallback_HostValidate gWebCallback_HostValidate
webCallback for HOST validation.
Definition upnpapi.cpp:271
Upnp_FunPtr GetCallBackFn(UpnpClient_Handle Hnd)
Get callback function ptr from a handle.
Definition upnpapi.cpp:3243
int UpnpCloseHttpGet(void *Handle)
Closes the connection and frees memory that was allocated for the handle parameter.
Definition upnpapi.cpp:3013
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:2005
int UpnpVirtualDir_set_GetInfoCallback(VDCallback_GetInfo callback)
Sets the get_info callback function to be used to access a web directory.
Definition upnpapi.cpp:3599
in_port_t LOCAL_PORT_V6_ULA_GUA
IPv6 ULA or GUA port for the mini-server.
Definition upnpapi.cpp:317
unsigned gIF_IPV6_ULA_GUA_PREFIX_LENGTH
IPv6 ULA or GUA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:308
int UpnpRegisterClient(Upnp_FunPtr Fun, const void *Cookie, UpnpClient_Handle *Hnd)
Registers a control point application with the UPnP Library.
Definition upnpapi.cpp:1409
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:2969
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:2345
struct VirtualDirCallbacks virtualDirCallback
This structure is for virtual directory callbacks.
Definition upnpapi.cpp:247
Upnp_Handle_Type GetHandleInfo(UpnpClient_Handle Hnd, Handle_Info **HndInfo)
Get handle information.
Definition upnpapi.cpp:3342
void UpnpThreadDistribution(struct UpnpNonblockParam *Param)
Schedule async functions in threadpool.
Definition upnpapi.cpp:3142
ThreadPool gSendThreadPool
Send thread pool.
Definition upnpapi.cpp:259
char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN]
Static buffer to contain interface IPv6 unique-local or globally-unique address (ULA or GUA)....
Definition upnpapi.cpp:305
void UpnpSetHostValidateCallback(WebCallback_HostValidate callback, void *cookie)
Set callback for validating HTTP requests HOST header values.
Definition upnpapi.cpp:3589
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:2959
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:1311
static int UpnpInitStartServers(in_port_t DestPort)
Finishes initializing the UPnP SDK.
Definition upnpapi.cpp:564
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:1724
int UpnpRenewSubscription(UpnpClient_Handle Hnd, int *TimeOut, const Upnp_SID SubsId)
Renews a subscription that is about to expire.
Definition upnpapi.cpp:2182
ThreadPool gRecvThreadPool
Receive thread pool.
Definition upnpapi.cpp:262
int UpnpEnableWebserver(int enable)
Enables or disables the webserver.
Definition upnpapi.cpp:3565
static void free_action_arg(job_arg *arg)
Free memory associated with an action job's argument.
Definition upnpapi.cpp:404
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:2945
int UpnpDownloadUrlItem(const char *url, char **outBuf, char *contentType)
Downloads a file specified in a URL.
Definition upnpapi.cpp:3058
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:646
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:1320
static int UpnpInitPreamble()
Performs the initial steps in initializing the UPnP SDK.
Definition upnpapi.cpp:497
int UpnpCancelHttpGet(void *Handle)
Set the cancel flag of the handle parameter.
Definition upnpapi.cpp:3011
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:3048
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:3696
int gAllowLiteralHostRedirection
Allow literal host names redirection to numeric host names.
Definition upnpapi.cpp:277
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:3027
int PrintHandleInfo(UpnpClient_Handle Hnd)
Print handle info.
Definition upnpapi.cpp:3364
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:2071
char * UpnpGetServerIp6Address()
Returns the IPv6 link-local listening ip address.
Definition upnpapi.cpp:792
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:2986
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:1020
Upnp_SID gUpnpSdkNLSuuid
Global variable used in discovery notifications.
Definition upnpapi.cpp:373
pthread_rwlock_t GlobalHndRWLock
rwlock to synchronize handles (root device or control point handle).
Definition upnpapi.cpp:253
unsigned short UpnpGetServerPort()
Returns the internal server IPv4 UPnP listening port.
Definition upnpapi.cpp:756
int UpnpVirtualDir_set_WriteCallback(VDCallback_Write callback)
Sets the write callback function to be used to access a web directory.
Definition upnpapi.cpp:3632
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:2955
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:3305
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:3004
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:2235
char * UpnpGetServerUlaGuaIp6Address()
Returns the IPv6 unique-local or globally-unique listening ip address.
Definition upnpapi.cpp:803
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:2117
unsigned gIF_IPV6_PREFIX_LENGTH
IPv6 LLA prefix length. (extern'ed in upnp.h)
Definition upnpapi.cpp:295
int UpnpVirtualDir_set_SeekCallback(VDCallback_Seek callback)
Sets the seek callback function to be used to access a web directory.
Definition upnpapi.cpp:3643
int UpnpFinish()
Terminates the Linux SDK for UPnP Devices.
Definition upnpapi.cpp:684
int UpnpSetMaxSubscriptions(UpnpDevice_Handle Hnd, int MaxSubscriptions)
Sets the maximum number of subscriptions accepted per service.
Definition upnpapi.cpp:1869
static int UpnpInitMutexes()
Initializes the global mutexes used by the UPnP SDK.
Definition upnpapi.cpp:422
void * gWebCallback_HostValidateCookie
Cookie to the webCallback for HOST validation.
Definition upnpapi.cpp:274
int UpnpVirtualDir_set_ReadCallback(VDCallback_Read callback)
Sets the read callback function to be used to access a web directory.
Definition upnpapi.cpp:3621
unsigned short UpnpGetServerPort6()
Returns the internal server IPv6 link-local (LLA) UPnP listening port.
Definition upnpapi.cpp:763
size_t g_maxContentLength
Maximum content-length (in bytes) that the SDK will process on an incoming packet.
Definition upnpapi.cpp:327
int UpnpSetWebServerRootDir(const char *rootDir)
Sets the document root directory for the internal web server.
Definition upnpapi.cpp:3398
virtualDirList * pVirtualDirList
Pointer to the virtual directory list.
Definition upnpapi.cpp:250
static int GetNameForAlias(char *name, char **alias)
Determines alias for given name which is a file name or URL.
Definition upnpapi.cpp:1516
int g_UpnpSdkEQMaxLen
Global variable to determines the maximum number of events.
Definition upnpapi.cpp:335
int UpnpCloseHttpConnection(void *handle)
Closes the connection created with UpnpOpenHttpConnection() and frees any memory associated with the ...
Definition upnpapi.cpp:3052
in_port_t LOCAL_PORT_V6
IPv6 LLA port for the mini-server.
Definition upnpapi.cpp:314
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:2300
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:2832
int UpnpHttpGetProgress(void *Handle, size_t *length, size_t *total)
Retrieve progress information of a http-get transfer.
Definition upnpapi.cpp:3019
int UpnpSetMaxSubscriptionTimeOut(UpnpDevice_Handle Hnd, int MaxSubscriptionTimeOut)
Sets the maximum time-out accepted for a subscription request or renewal.
Definition upnpapi.cpp:1902
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:1569
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:3015
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:866
int UpnpSetContentLength(UpnpClient_Handle Hnd, size_t contentLength)
Sets the content-length that the SDK will process on an incoming SOAP requests or responses.
Definition upnpapi.cpp:3666
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:1718
unsigned short UpnpGetServerUlaGuaPort6()
Returns the internal server IPv6 ULA or GUA UPnP listening port.
Definition upnpapi.cpp:774
int UpnpSdkInit
Global variable to denote the state of Upnp SDK == 0 if uninitialized, == 1 if initialized.
Definition upnpapi.cpp:350
static int GetFreeHandle()
Get a free UPnP Unit handle.
Definition upnpapi.cpp:822
static void get_server_addr(struct sockaddr *serverAddr)
Fill the sockadr with IPv4 miniserver information.
Definition upnpapi.cpp:1542
in_port_t LOCAL_PORT_V4
local IPv4 port for the mini-server
Definition upnpapi.cpp:311
static int UpnpInitThreadPools()
Initializes the global threadm pools used by the UPnP SDK.
Definition upnpapi.cpp:450
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:2538
int UpnpAddVirtualDir(const char *newDirName, const void *cookie, const void **oldcookie)
Adds a web directory mapping.
Definition upnpapi.cpp:3424
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:1939
int UpnpSdkDeviceRegisteredV4
Global variable to denote the state of Upnp SDK IPv4 device registration.
Definition upnpapi.cpp:361
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:3268
int UpnpUnRegisterRootDeviceLowPower(UpnpDevice_Handle Hnd, int PowerState, int SleepPeriod, int RegistrationState)
Unregisters a root device registered with UpnpRegisterRootDevice(), UpnpRegisterRootDevice2(),...
Definition upnpapi.cpp:1337
int UpnpSdkClientRegistered
Global variable to denote the state of Upnp SDK client registration.
Definition upnpapi.cpp:355
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:2460
void AutoAdvertise(void *input)
This function is a timer thread scheduled by UpnpSendAdvertisement to the send advetisement again.
Definition upnpapi.cpp:3389
int UpnpUnRegisterRootDevice(UpnpDevice_Handle Hnd)
Unregisters a root device registered with UpnpRegisterRootDevice(), UpnpRegisterRootDevice2(),...
Definition upnpapi.cpp:1331
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:2720
int UpnpRemoveVirtualDir(const char *dirName)
Removes a web directory mapping made with UpnpAddVirtualDir().
Definition upnpapi.cpp:3499
int UpnpEndHttpRequest(void *handle, int timeout)
Indicates the end of a HTTP request previously made by UpnpMakeHttpRequest().
Definition upnpapi.cpp:3038
void UpnpRemoveAllVirtualDirs()
Removes all web directory mappings.
Definition upnpapi.cpp:3545
int UpnpDownloadXmlDoc(const char *url, IXML_Document **xmlDoc)
Downloads an XML document specified in a URL.
Definition upnpapi.cpp:3080
static void get_server_addr6(struct sockaddr *serverAddr)
Fill the sockadr with IPv6 miniserver information.
Definition upnpapi.cpp:1557
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:3034
char gIF_IPV4[INET_ADDRSTRLEN]
Static buffer to contain interface IPv4 address. (extern'ed in upnp.h)
Definition upnpapi.cpp:284
TimerThread gTimerThread
Global timer thread.
Definition upnpapi.cpp:256
static void free_advertise_arg(job_arg *arg)
Free memory associated with advertise job's argument.
Definition upnpapi.cpp:392
int UpnpVirtualDir_set_OpenCallback(VDCallback_Open callback)
Sets the open callback function to be used to access a web directory.
Definition upnpapi.cpp:3610
char gIF_NAME[LINE_SIZE]
Static buffer to contain interface name. (extern'ed in upnp.h)
Definition upnpapi.cpp:280
unsigned gIF_INDEX
Contains network interface index of the link local address gIF_IPV6 that is used as its scope_id.
Definition upnpapi.cpp:299
ThreadPool gMiniServerThreadPool
Mini server thread pool.
Definition upnpapi.cpp:265
membuffer gWebserverCorsString
Definition webserver.hpp:47
char gIF_IPV4_NETMASK[INET_ADDRSTRLEN]
Static buffer to contain interface IPv4 netmask. (extern'ed in upnp.h)
Definition upnpapi.cpp:288
static int FreeHandle(int Upnp_Handle)
Free handle.
Definition upnpapi.cpp:839
int g_UpnpSdkEQMaxAge
Global variable to determine the maximum number of seconds which an event can spend on a subscription...
Definition upnpapi.cpp:346
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:2586
char gIF_IPV6[INET6_ADDRSTRLEN]
Static buffer to contain interface IPv6 link-local address (LLA). (extern'ed in upnp....
Definition upnpapi.cpp:292
int UpnpSdkDeviceregisteredV6
Global variable to denote the state of Upnp SDK IPv6 device registration.
Definition upnpapi.cpp:367
void UpnpSetAllowLiteralHostRedirection(int enable)
Enable or disable literal IP redirection.
Definition upnpapi.cpp:3595
int UpnpUnRegisterClient(UpnpClient_Handle Hnd)
Unregisters a control point application, unsubscribing all active subscriptions.
Definition upnpapi.cpp:1458
Upnp_Handle_Type GetClientHandleInfo(UpnpClient_Handle *client_handle_out, struct Handle_Info **HndInfo)
Get client handle info.
Definition upnpapi.cpp:3248
int UpnpIsWebserverEnabled()
Returns the status of the webserver.
Definition upnpapi.cpp:3581
int UpnpOpenHttpConnection(const char *url, void **handle, int timeout)
Opens a connection to the server.
Definition upnpapi.cpp:3023
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:3411
WebServerState bWebServerState
Flag to indicate the state of web server.
Definition upnpapi.cpp:268
char * UpnpGetServerIpAddress()
Returns the local IPv4 listening ip address.
Definition upnpapi.cpp:785
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:3042
int UpnpVirtualDir_set_CloseCallback(VDCallback_Close callback)
Sets the close callback function to be used to access a web directory.
Definition upnpapi.cpp:3654
Inititalize the compatible library before it can be used.
IXML_Document * Act
UpnpNonblockParam
Definition upnpapi.hpp:273
Upnp_Handle_Type HType
Handle Type.
Definition upnpapi.hpp:85
IXML_Document * Header
UpnpNonblockParam
Definition upnpapi.hpp:272
char * Cookie
UpnpNonblockParam
Definition upnpapi.hpp:270
IXML_NodeList * ServiceList
List of services in the description document.
Definition upnpapi.hpp:106
int aliasInstalled
0 = not installed; otherwise installed.
Definition upnpapi.hpp:88
int Handle
UpnpNonblockParam
Definition upnpapi.hpp:260
#define HandleLock()
HandleLock.
Definition upnpapi.hpp:138
Upnp_FunPtr Fun
UpnpNonblockParam
Definition upnpapi.hpp:271
Upnp_Handle_Type
Definition upnpapi.hpp:75
char Url[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:268
GenlibClientSubscription * ClientSubList
Client subscription list.
Definition upnpapi.hpp:118
#define DEFAULT_MAXAGE
DEFAULT_MAXAGE.
Definition upnpapi.hpp:56
service_table ServiceTable
Table holding subscriptions and URL information.
Definition upnpapi.hpp:108
int SleepPeriod
Sleep Period as defined by UPnP Low Power.
Definition upnpapi.hpp:100
#define DEFAULT_MX
DEFAULT_MX.
Definition upnpapi.hpp:53
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:94
int RegistrationState
Registration State as defined by UPnP Low Power.
Definition upnpapi.hpp:101
char DescURL[LINE_SIZE]
URL for the use of SSDP.
Definition upnpapi.hpp:93
Upnp_SID SubsId
UpnpNonblockParam
Definition upnpapi.hpp:269
#define HandleUnlock()
HandleUnlock.
Definition upnpapi.hpp:147
IXML_Document * DescDocument
Description parsed in terms of DOM document.
Definition upnpapi.hpp:103
UpnpFunName FunName
UpnpNonblockParam
Definition upnpapi.hpp:259
int TimeOut
UpnpNonblockParam
Definition upnpapi.hpp:261
int PowerState
Power State as defined by UPnP Low Power.
Definition upnpapi.hpp:99
WebServerState
Possible status of the internal webserver.
Definition upnpapi.hpp:282
char * Cookie
???
Definition upnpapi.hpp:87
Upnp_FunPtr Callback
Callback function pointer.
Definition upnpapi.hpp:86
constexpr int NUM_HANDLE
Maximal number of available UPnP Unit handles.
Definition upnpapi.hpp:64
int MaxSubscriptionTimeOut
???
Definition upnpapi.hpp:110
int MaxSubscriptions
???
Definition upnpapi.hpp:109
LinkedList SsdpSearchList
Active SSDP searches.
Definition upnpapi.hpp:119
IXML_NodeList * DeviceList
List of devices in the description document.
Definition upnpapi.hpp:104
int MaxAge
Advertisement timeout.
Definition upnpapi.hpp:98
char VarName[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:262
int DeviceAf
Address family: AF_INET6 or AF_INET.
Definition upnpapi.hpp:111
#define MAX_SOAP_CONTENT_LENGTH
MAX_SOAP_CONTENT_LENGTH.
Definition upnpapi.hpp:61
char ServiceType[NAME_SIZE]
UpnpNonblockParam
Definition upnpapi.hpp:266
#define HandleReadLock()
HandleReadLock.
Definition upnpapi.hpp:144
Data to be stored in handle table for Handle Info.
Definition upnpapi.hpp:84
UpnpNonblockParam.
Definition upnpapi.hpp:256
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