b59ec7d838
Fix for bug introduced in samples code in svn revision 502, commit
git:25c908c558c8e60eb386c155a6b93add447ffec0
Sample device and combo were aborting with the message:
"***** SampleUtil_Initialize was called multiple times!"
(cherry picked from commit ef7edf6cf8
)
815 lines
24 KiB
C
815 lines
24 KiB
C
/*******************************************************************************
|
|
*
|
|
* Copyright (c) 2000-2003 Intel Corporation
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* - Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
* - Neither name of Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
#include "sample_util.h"
|
|
|
|
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
#if !UPNP_HAVE_TOOLS
|
|
# error "Need upnptools.h to compile samples ; try ./configure --enable-tools"
|
|
#endif
|
|
|
|
|
|
static int initialize_init = 1;
|
|
static int initialize_register = 1;
|
|
|
|
/*! Function pointers to use for displaying formatted strings.
|
|
* Set on Initialization of device. */
|
|
print_string gPrintFun = NULL;
|
|
state_update gStateUpdateFun = NULL;
|
|
|
|
/*! mutex to control displaying of events */
|
|
ithread_mutex_t display_mutex;
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_Initialize
|
|
*
|
|
* Description:
|
|
* Initializes the sample util. Must be called before any sample util
|
|
* functions. May be called multiple times.
|
|
* But the initialization is done only once.
|
|
*
|
|
* Parameters:
|
|
* print_function - print function to use in SampleUtil_Print
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_Initialize(print_string print_function)
|
|
{
|
|
if (initialize_init) {
|
|
ithread_mutexattr_t attr;
|
|
|
|
ithread_mutexattr_init(&attr);
|
|
ithread_mutexattr_setkind_np(&attr, ITHREAD_MUTEX_RECURSIVE_NP);
|
|
ithread_mutex_init(&display_mutex, &attr);
|
|
ithread_mutexattr_destroy(&attr);
|
|
|
|
/* To shut up valgrind mutex warning. */
|
|
ithread_mutex_lock(&display_mutex);
|
|
gPrintFun = print_function;
|
|
ithread_mutex_unlock(&display_mutex);
|
|
|
|
initialize_init = 0;
|
|
}
|
|
|
|
return UPNP_E_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_RegisterUpdateFunction
|
|
*
|
|
* Description:
|
|
*
|
|
* Parameters:
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_RegisterUpdateFunction(state_update update_function)
|
|
{
|
|
if (initialize_register) {
|
|
gStateUpdateFun = update_function;
|
|
initialize_register = 0;
|
|
}
|
|
|
|
return UPNP_E_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_Finish
|
|
*
|
|
* Description:
|
|
* Releases Resources held by sample util.
|
|
*
|
|
* Parameters:
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_Finish()
|
|
{
|
|
ithread_mutex_destroy(&display_mutex);
|
|
gPrintFun = NULL;
|
|
gStateUpdateFun = NULL;
|
|
initialize_init = 1;
|
|
initialize_register = 1;
|
|
|
|
return UPNP_E_SUCCESS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_GetElementValue
|
|
*
|
|
* Description:
|
|
* Given a DOM node such as <Channel>11</Channel>, this routine
|
|
* extracts the value (e.g., 11) from the node and returns it as
|
|
* a string. The string must be freed by the caller using
|
|
* free.
|
|
*
|
|
* Parameters:
|
|
* node -- The DOM node from which to extract the value
|
|
*
|
|
******************************************************************************/
|
|
|
|
char *SampleUtil_GetElementValue(IN IXML_Element *element)
|
|
{
|
|
IXML_Node *child = ixmlNode_getFirstChild((IXML_Node *)element);
|
|
char *temp = NULL;
|
|
|
|
if (child != 0 && ixmlNode_getNodeType(child) == eTEXT_NODE) {
|
|
temp = strdup(ixmlNode_getNodeValue(child));
|
|
}
|
|
|
|
return temp;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_GetFirstServiceList
|
|
*
|
|
* Description:
|
|
* Given a DOM node representing a UPnP Device Description Document,
|
|
* this routine parses the document and finds the first service list
|
|
* (i.e., the service list for the root device). The service list
|
|
* is returned as a DOM node list.
|
|
*
|
|
* Parameters:
|
|
* node -- The DOM node from which to extract the service list
|
|
*
|
|
******************************************************************************/
|
|
IXML_NodeList *SampleUtil_GetFirstServiceList(IN IXML_Document *doc)
|
|
{
|
|
IXML_NodeList *ServiceList = NULL;
|
|
IXML_NodeList *servlistnodelist = NULL;
|
|
IXML_Node *servlistnode = NULL;
|
|
|
|
servlistnodelist =
|
|
ixmlDocument_getElementsByTagName( doc, "serviceList" );
|
|
if (servlistnodelist && ixmlNodeList_length(servlistnodelist)) {
|
|
/* we only care about the first service list, from the root
|
|
* device */
|
|
servlistnode = ixmlNodeList_item(servlistnodelist, 0);
|
|
|
|
/* create as list of DOM nodes */
|
|
ServiceList = ixmlElement_getElementsByTagName(
|
|
(IXML_Element *)servlistnode, "service");
|
|
}
|
|
if (servlistnodelist) {
|
|
ixmlNodeList_free(servlistnodelist);
|
|
}
|
|
|
|
return ServiceList;
|
|
}
|
|
|
|
/*
|
|
* Obtain the service list
|
|
* n == 0 the first
|
|
* n == 1 the next in the device list, etc..
|
|
*
|
|
*/
|
|
IXML_NodeList *SampleUtil_GetNthServiceList(IN IXML_Document *doc , int n)
|
|
{
|
|
IXML_NodeList *ServiceList = NULL;
|
|
IXML_NodeList *servlistnodelist = NULL;
|
|
IXML_Node *servlistnode = NULL;
|
|
|
|
/*
|
|
* ixmlDocument_getElementsByTagName()
|
|
* Returns a NodeList of all Elements that match the given
|
|
* tag name in the order in which they were encountered in a preorder
|
|
* traversal of the Document tree.
|
|
*
|
|
* return (NodeList*) A pointer to a NodeList containing the
|
|
* matching items or NULL on an error.
|
|
*/
|
|
SampleUtil_Print("SampleUtil_GetNthServiceList called : n = %d\n", n);
|
|
servlistnodelist =
|
|
ixmlDocument_getElementsByTagName(doc, "serviceList");
|
|
if (servlistnodelist &&
|
|
ixmlNodeList_length(servlistnodelist) &&
|
|
n < ixmlNodeList_length(servlistnodelist)) {
|
|
/* For the first service list (from the root device),
|
|
* we pass 0 */
|
|
/*servlistnode = ixmlNodeList_item( servlistnodelist, 0 );*/
|
|
|
|
/* Retrieves a Node from a NodeList} specified by a
|
|
* numerical index.
|
|
*
|
|
* return (Node*) A pointer to a Node or NULL if there was an
|
|
* error.
|
|
*/
|
|
servlistnode = ixmlNodeList_item(servlistnodelist, n);
|
|
|
|
assert(servlistnode != 0);
|
|
|
|
/* create as list of DOM nodes */
|
|
ServiceList = ixmlElement_getElementsByTagName(
|
|
(IXML_Element *)servlistnode, "service");
|
|
}
|
|
|
|
if (servlistnodelist) {
|
|
ixmlNodeList_free(servlistnodelist);
|
|
}
|
|
|
|
return ServiceList;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_GetFirstDocumentItem
|
|
*
|
|
* Description:
|
|
* Given a document node, this routine searches for the first element
|
|
* named by the input string item, and returns its value as a string.
|
|
* String must be freed by caller using free.
|
|
* Parameters:
|
|
* doc -- The DOM document from which to extract the value
|
|
* item -- The item to search for
|
|
*
|
|
******************************************************************************/
|
|
char *SampleUtil_GetFirstDocumentItem(
|
|
IN IXML_Document *doc, IN const char *item)
|
|
{
|
|
IXML_NodeList *nodeList = NULL;
|
|
IXML_Node *textNode = NULL;
|
|
IXML_Node *tmpNode = NULL;
|
|
char *ret = NULL;
|
|
|
|
nodeList = ixmlDocument_getElementsByTagName(doc, (char *)item);
|
|
if (nodeList) {
|
|
tmpNode = ixmlNodeList_item(nodeList, 0);
|
|
if (tmpNode) {
|
|
textNode = ixmlNode_getFirstChild(tmpNode);
|
|
if (!textNode) {
|
|
SampleUtil_Print("sample_util.c: (bug) "
|
|
"ixmlNode_getFirstChild(tmpNode) "
|
|
"returned NULL\n");
|
|
ret = strdup("");
|
|
goto epilogue;
|
|
}
|
|
if (!ixmlNode_getNodeValue(textNode)) {
|
|
SampleUtil_Print("ixmlNode_getNodeValue "
|
|
"returned NULL\n");
|
|
ret = strdup("");
|
|
goto epilogue;
|
|
} else {
|
|
ret = strdup(ixmlNode_getNodeValue(textNode));
|
|
}
|
|
} else {
|
|
SampleUtil_Print("ixmlNode_getFirstChild(tmpNode) "
|
|
"returned NULL\n");
|
|
goto epilogue;
|
|
}
|
|
} else {
|
|
SampleUtil_Print("Error finding %s in XML Node\n", item);
|
|
goto epilogue;
|
|
}
|
|
|
|
epilogue:
|
|
if (nodeList) {
|
|
ixmlNodeList_free(nodeList);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_GetFirstElementItem
|
|
*
|
|
* Description:
|
|
* Given a DOM element, this routine searches for the first element
|
|
* named by the input string item, and returns its value as a string.
|
|
* The string must be freed using free.
|
|
* Parameters:
|
|
* node -- The DOM element from which to extract the value
|
|
* item -- The item to search for
|
|
*
|
|
******************************************************************************/
|
|
char *SampleUtil_GetFirstElementItem(
|
|
IN IXML_Element *element, IN const char *item)
|
|
{
|
|
IXML_NodeList *nodeList = NULL;
|
|
IXML_Node *textNode = NULL;
|
|
IXML_Node *tmpNode = NULL;
|
|
char *ret = NULL;
|
|
|
|
nodeList = ixmlElement_getElementsByTagName(element, (char *)item);
|
|
if (nodeList == NULL) {
|
|
SampleUtil_Print( "Error finding %s in XML Node\n", item);
|
|
|
|
return NULL;
|
|
}
|
|
tmpNode = ixmlNodeList_item(nodeList, 0);
|
|
if (tmpNode) {
|
|
SampleUtil_Print("Error finding %s value in XML Node\n", item);
|
|
ixmlNodeList_free(nodeList);
|
|
|
|
return NULL;
|
|
}
|
|
textNode = ixmlNode_getFirstChild(tmpNode);
|
|
ret = strdup(ixmlNode_getNodeValue(textNode));
|
|
if (!ret) {
|
|
SampleUtil_Print("Error allocating memory for %s in XML Node\n",
|
|
item);
|
|
ixmlNodeList_free(nodeList);
|
|
|
|
return NULL;
|
|
}
|
|
ixmlNodeList_free(nodeList);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_PrintEventType
|
|
*
|
|
* Description:
|
|
* Prints a callback event type as a string.
|
|
*
|
|
* Parameters:
|
|
* S -- The callback event
|
|
*
|
|
******************************************************************************/
|
|
void SampleUtil_PrintEventType(IN Upnp_EventType S)
|
|
{
|
|
switch (S) {
|
|
/* Discovery */
|
|
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
|
|
SampleUtil_Print("UPNP_DISCOVERY_ADVERTISEMENT_ALIVE\n");
|
|
break;
|
|
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
|
|
SampleUtil_Print("UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE\n");
|
|
break;
|
|
case UPNP_DISCOVERY_SEARCH_RESULT:
|
|
SampleUtil_Print( "UPNP_DISCOVERY_SEARCH_RESULT\n");
|
|
break;
|
|
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
|
|
SampleUtil_Print( "UPNP_DISCOVERY_SEARCH_TIMEOUT\n");
|
|
break;
|
|
/* SOAP */
|
|
case UPNP_CONTROL_ACTION_REQUEST:
|
|
SampleUtil_Print("UPNP_CONTROL_ACTION_REQUEST\n");
|
|
break;
|
|
case UPNP_CONTROL_ACTION_COMPLETE:
|
|
SampleUtil_Print("UPNP_CONTROL_ACTION_COMPLETE\n");
|
|
break;
|
|
case UPNP_CONTROL_GET_VAR_REQUEST:
|
|
SampleUtil_Print("UPNP_CONTROL_GET_VAR_REQUEST\n");
|
|
break;
|
|
case UPNP_CONTROL_GET_VAR_COMPLETE:
|
|
SampleUtil_Print("UPNP_CONTROL_GET_VAR_COMPLETE\n");
|
|
break;
|
|
/* GENA */
|
|
case UPNP_EVENT_SUBSCRIPTION_REQUEST:
|
|
SampleUtil_Print("UPNP_EVENT_SUBSCRIPTION_REQUEST\n");
|
|
break;
|
|
case UPNP_EVENT_RECEIVED:
|
|
SampleUtil_Print("UPNP_EVENT_RECEIVED\n");
|
|
break;
|
|
case UPNP_EVENT_RENEWAL_COMPLETE:
|
|
SampleUtil_Print("UPNP_EVENT_RENEWAL_COMPLETE\n");
|
|
break;
|
|
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
|
|
SampleUtil_Print("UPNP_EVENT_SUBSCRIBE_COMPLETE\n");
|
|
break;
|
|
case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
|
|
SampleUtil_Print("UPNP_EVENT_UNSUBSCRIBE_COMPLETE\n");
|
|
break;
|
|
case UPNP_EVENT_AUTORENEWAL_FAILED:
|
|
SampleUtil_Print("UPNP_EVENT_AUTORENEWAL_FAILED\n");
|
|
break;
|
|
case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
|
|
SampleUtil_Print("UPNP_EVENT_SUBSCRIPTION_EXPIRED\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_PrintEvent
|
|
*
|
|
* Description:
|
|
* Prints callback event structure details.
|
|
*
|
|
* Parameters:
|
|
* EventType -- The type of callback event
|
|
* Event -- The callback event structure
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_PrintEvent(IN Upnp_EventType EventType, IN void *Event)
|
|
{
|
|
ithread_mutex_lock(&display_mutex);
|
|
|
|
SampleUtil_Print(
|
|
"======================================================================\n"
|
|
"----------------------------------------------------------------------\n");
|
|
SampleUtil_PrintEventType(EventType);
|
|
switch (EventType) {
|
|
/* SSDP */
|
|
case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
|
|
case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
|
|
case UPNP_DISCOVERY_SEARCH_RESULT: {
|
|
UpnpDiscovery *d_event = (UpnpDiscovery *)Event;
|
|
SampleUtil_Print(
|
|
"ErrCode = %d\n"
|
|
"Expires = %d\n"
|
|
"DeviceId = %s\n"
|
|
"DeviceType = %s\n"
|
|
"ServiceType = %s\n"
|
|
"ServiceVer = %s\n"
|
|
"Location = %s\n"
|
|
"OS = %s\n"
|
|
"Date = %s\n"
|
|
"Ext = %s\n",
|
|
UpnpDiscovery_get_ErrCode(d_event),
|
|
UpnpDiscovery_get_Expires(d_event),
|
|
UpnpString_get_String(UpnpDiscovery_get_DeviceID(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_DeviceType(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_ServiceType(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_ServiceVer(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_Location(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_Os(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_Date(d_event)),
|
|
UpnpString_get_String(UpnpDiscovery_get_Ext(d_event)));
|
|
break;
|
|
}
|
|
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
|
|
/* Nothing to print out here */
|
|
break;
|
|
/* SOAP */
|
|
case UPNP_CONTROL_ACTION_REQUEST: {
|
|
UpnpActionRequest *a_event = (UpnpActionRequest *)Event;
|
|
IXML_Document *actionRequestDoc = NULL;
|
|
IXML_Document *actionResultDoc = NULL;
|
|
char *xmlbuff = NULL;
|
|
|
|
SampleUtil_Print(
|
|
"ErrCode = %d\n"
|
|
"ErrStr = %s\n"
|
|
"ActionName = %s\n"
|
|
"UDN = %s\n"
|
|
"ServiceID = %s\n",
|
|
UpnpActionRequest_get_ErrCode(a_event),
|
|
UpnpString_get_String(UpnpActionRequest_get_ErrStr(a_event)),
|
|
UpnpString_get_String(UpnpActionRequest_get_ActionName(a_event)),
|
|
UpnpString_get_String(UpnpActionRequest_get_DevUDN(a_event)),
|
|
UpnpString_get_String(UpnpActionRequest_get_ServiceID(a_event)));
|
|
actionRequestDoc = UpnpActionRequest_get_ActionRequest(a_event);
|
|
if (actionRequestDoc) {
|
|
xmlbuff = ixmlPrintNode((IXML_Node *)actionRequestDoc);
|
|
if (xmlbuff) {
|
|
SampleUtil_Print("ActRequest = %s\n", xmlbuff);
|
|
ixmlFreeDOMString(xmlbuff);
|
|
}
|
|
xmlbuff = NULL;
|
|
} else {
|
|
SampleUtil_Print("ActRequest = (null)\n");
|
|
}
|
|
actionResultDoc = UpnpActionRequest_get_ActionResult(a_event);
|
|
if (actionResultDoc) {
|
|
xmlbuff = ixmlPrintNode((IXML_Node *)actionResultDoc);
|
|
if (xmlbuff) {
|
|
SampleUtil_Print("ActResult = %s\n", xmlbuff);
|
|
ixmlFreeDOMString(xmlbuff);
|
|
}
|
|
xmlbuff = NULL;
|
|
} else {
|
|
SampleUtil_Print("ActResult = (null)\n");
|
|
}
|
|
break;
|
|
}
|
|
case UPNP_CONTROL_ACTION_COMPLETE: {
|
|
UpnpActionComplete *a_event = (UpnpActionComplete *)Event;
|
|
char *xmlbuff = NULL;
|
|
int errCode = UpnpActionComplete_get_ErrCode(a_event);
|
|
const char *ctrlURL = UpnpString_get_String(
|
|
UpnpActionComplete_get_CtrlUrl(a_event));
|
|
IXML_Document *actionRequest =
|
|
UpnpActionComplete_get_ActionRequest(a_event);
|
|
IXML_Document *actionResult =
|
|
UpnpActionComplete_get_ActionResult(a_event);
|
|
|
|
SampleUtil_Print(
|
|
"ErrCode = %d\n"
|
|
"CtrlUrl = %s\n",
|
|
errCode, ctrlURL);
|
|
if (actionRequest) {
|
|
xmlbuff = ixmlPrintNode((IXML_Node *)actionRequest);
|
|
if (xmlbuff) {
|
|
SampleUtil_Print("ActRequest = %s\n", xmlbuff);
|
|
ixmlFreeDOMString(xmlbuff);
|
|
}
|
|
xmlbuff = NULL;
|
|
} else {
|
|
SampleUtil_Print("ActRequest = (null)\n");
|
|
}
|
|
if (actionResult) {
|
|
xmlbuff = ixmlPrintNode((IXML_Node *)actionResult);
|
|
if (xmlbuff) {
|
|
SampleUtil_Print("ActResult = %s\n", xmlbuff);
|
|
ixmlFreeDOMString(xmlbuff);
|
|
}
|
|
xmlbuff = NULL;
|
|
} else {
|
|
SampleUtil_Print("ActResult = (null)\n");
|
|
}
|
|
break;
|
|
}
|
|
case UPNP_CONTROL_GET_VAR_REQUEST: {
|
|
UpnpStateVarRequest *sv_event = (UpnpStateVarRequest *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"ErrCode = %d\n"
|
|
"ErrStr = %s\n"
|
|
"UDN = %s\n"
|
|
"ServiceID = %s\n"
|
|
"StateVarName= %s\n"
|
|
"CurrentVal = %s\n",
|
|
UpnpStateVarRequest_get_ErrCode(sv_event),
|
|
UpnpString_get_String(UpnpStateVarRequest_get_ErrStr(sv_event)),
|
|
UpnpString_get_String(UpnpStateVarRequest_get_DevUDN(sv_event)),
|
|
UpnpString_get_String(UpnpStateVarRequest_get_ServiceID(sv_event)),
|
|
UpnpString_get_String(UpnpStateVarRequest_get_StateVarName(sv_event)),
|
|
UpnpStateVarRequest_get_CurrentVal(sv_event));
|
|
break;
|
|
}
|
|
case UPNP_CONTROL_GET_VAR_COMPLETE: {
|
|
UpnpStateVarComplete *sv_event = (UpnpStateVarComplete *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"ErrCode = %d\n"
|
|
"CtrlUrl = %s\n"
|
|
"StateVarName= %s\n"
|
|
"CurrentVal = %s\n",
|
|
UpnpStateVarComplete_get_ErrCode(sv_event),
|
|
UpnpString_get_String(UpnpStateVarComplete_get_CtrlUrl(sv_event)),
|
|
UpnpString_get_String(UpnpStateVarComplete_get_StateVarName(sv_event)),
|
|
UpnpStateVarComplete_get_CurrentVal(sv_event));
|
|
break;
|
|
}
|
|
|
|
/* GENA */
|
|
case UPNP_EVENT_SUBSCRIPTION_REQUEST: {
|
|
UpnpSubscriptionRequest *sr_event = (UpnpSubscriptionRequest *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"ServiceID = %s\n"
|
|
"UDN = %s\n"
|
|
"SID = %s\n",
|
|
UpnpString_get_String(UpnpSubscriptionRequest_get_ServiceId(sr_event)),
|
|
UpnpString_get_String(UpnpSubscriptionRequest_get_UDN(sr_event)),
|
|
UpnpString_get_String(UpnpSubscriptionRequest_get_SID(sr_event)));
|
|
break;
|
|
}
|
|
case UPNP_EVENT_RECEIVED: {
|
|
UpnpEvent *e_event = (UpnpEvent *)Event;
|
|
char *xmlbuff = NULL;
|
|
|
|
xmlbuff = ixmlPrintNode(
|
|
(IXML_Node *)UpnpEvent_get_ChangedVariables(e_event));
|
|
SampleUtil_Print(
|
|
"SID = %s\n"
|
|
"EventKey = %d\n"
|
|
"ChangedVars = %s\n",
|
|
UpnpString_get_String(UpnpEvent_get_SID(e_event)),
|
|
UpnpEvent_get_EventKey(e_event),
|
|
xmlbuff);
|
|
ixmlFreeDOMString(xmlbuff);
|
|
break;
|
|
}
|
|
case UPNP_EVENT_RENEWAL_COMPLETE: {
|
|
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"SID = %s\n"
|
|
"ErrCode = %d\n"
|
|
"TimeOut = %d\n",
|
|
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
|
|
UpnpEventSubscribe_get_ErrCode(es_event),
|
|
UpnpEventSubscribe_get_TimeOut(es_event));
|
|
break;
|
|
}
|
|
case UPNP_EVENT_SUBSCRIBE_COMPLETE:
|
|
case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: {
|
|
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"SID = %s\n"
|
|
"ErrCode = %d\n"
|
|
"PublisherURL= %s\n"
|
|
"TimeOut = %d\n",
|
|
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
|
|
UpnpEventSubscribe_get_ErrCode(es_event),
|
|
UpnpString_get_String(UpnpEventSubscribe_get_PublisherUrl(es_event)),
|
|
UpnpEventSubscribe_get_TimeOut(es_event));
|
|
break;
|
|
}
|
|
case UPNP_EVENT_AUTORENEWAL_FAILED:
|
|
case UPNP_EVENT_SUBSCRIPTION_EXPIRED: {
|
|
UpnpEventSubscribe *es_event = (UpnpEventSubscribe *)Event;
|
|
|
|
SampleUtil_Print(
|
|
"SID = %s\n"
|
|
"ErrCode = %d\n"
|
|
"PublisherURL= %s\n"
|
|
"TimeOut = %d\n",
|
|
UpnpString_get_String(UpnpEventSubscribe_get_SID(es_event)),
|
|
UpnpEventSubscribe_get_ErrCode(es_event),
|
|
UpnpString_get_String(UpnpEventSubscribe_get_PublisherUrl(es_event)),
|
|
UpnpEventSubscribe_get_TimeOut(es_event));
|
|
break;
|
|
}
|
|
}
|
|
SampleUtil_Print(
|
|
"----------------------------------------------------------------------\n"
|
|
"======================================================================\n"
|
|
"\n\n\n");
|
|
|
|
ithread_mutex_unlock(&display_mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_FindAndParseService
|
|
*
|
|
* Description:
|
|
* This routine finds the first occurance of a service in a DOM representation
|
|
* of a description document and parses it.
|
|
*
|
|
* Parameters:
|
|
* DescDoc -- The DOM description document
|
|
* location -- The location of the description document
|
|
* serviceSearchType -- The type of service to search for
|
|
* serviceId -- OUT -- The service ID
|
|
* eventURL -- OUT -- The event URL for the service
|
|
* controlURL -- OUT -- The control URL for the service
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_FindAndParseService(
|
|
IN IXML_Document *DescDoc, IN const char *location, IN char *serviceType,
|
|
OUT char **serviceId, OUT char **eventURL, OUT char **controlURL)
|
|
{
|
|
int i;
|
|
int length;
|
|
int found = 0;
|
|
int ret;
|
|
int sindex = 0;
|
|
char *tempServiceType = NULL;
|
|
char *baseURL = NULL;
|
|
const char *base = NULL;
|
|
char *relcontrolURL = NULL;
|
|
char *releventURL = NULL;
|
|
IXML_NodeList *serviceList = NULL;
|
|
IXML_Element *service = NULL;
|
|
|
|
baseURL = SampleUtil_GetFirstDocumentItem(DescDoc, "URLBase");
|
|
if (baseURL) {
|
|
base = baseURL;
|
|
} else {
|
|
base = location;
|
|
}
|
|
|
|
/* Top level */
|
|
for (sindex = 0;
|
|
(serviceList = SampleUtil_GetNthServiceList(DescDoc , sindex)) != NULL;
|
|
sindex ++) {
|
|
tempServiceType = NULL;
|
|
relcontrolURL = NULL;
|
|
releventURL = NULL;
|
|
service = NULL;
|
|
|
|
/* serviceList = SampleUtil_GetFirstServiceList( DescDoc ); */
|
|
length = ixmlNodeList_length(serviceList);
|
|
for (i = 0; i < length; i++) {
|
|
service = (IXML_Element *)ixmlNodeList_item(serviceList, i);
|
|
tempServiceType =
|
|
SampleUtil_GetFirstElementItem(
|
|
(IXML_Element *)service, "serviceType");
|
|
if (strcmp(tempServiceType, serviceType) == 0) {
|
|
SampleUtil_Print("Found service: %s\n", serviceType);
|
|
*serviceId =
|
|
SampleUtil_GetFirstElementItem(service, "serviceId");
|
|
SampleUtil_Print("serviceId: %s\n", *serviceId);
|
|
relcontrolURL =
|
|
SampleUtil_GetFirstElementItem(service, "controlURL");
|
|
releventURL =
|
|
SampleUtil_GetFirstElementItem(service, "eventSubURL");
|
|
*controlURL =
|
|
malloc(strlen(base) + strlen(relcontrolURL)+1);
|
|
if (*controlURL) {
|
|
ret = UpnpResolveURL(base, relcontrolURL, *controlURL);
|
|
if (ret != UPNP_E_SUCCESS) {
|
|
SampleUtil_Print("Error generating controlURL from %s + %s\n",
|
|
base, relcontrolURL);
|
|
}
|
|
}
|
|
*eventURL = malloc(strlen(base) + strlen(releventURL)+1);
|
|
if (*eventURL) {
|
|
ret = UpnpResolveURL(base, releventURL, *eventURL);
|
|
if (ret != UPNP_E_SUCCESS) {
|
|
SampleUtil_Print("Error generating eventURL from %s + %s\n",
|
|
base, releventURL);
|
|
}
|
|
}
|
|
free(relcontrolURL);
|
|
free(releventURL);
|
|
relcontrolURL = NULL;
|
|
releventURL = NULL;
|
|
found = 1;
|
|
break;
|
|
}
|
|
free(tempServiceType);
|
|
tempServiceType = NULL;
|
|
}
|
|
free(tempServiceType);
|
|
tempServiceType = NULL;
|
|
if (serviceList) {
|
|
ixmlNodeList_free(serviceList);
|
|
}
|
|
serviceList = NULL;
|
|
}
|
|
free(baseURL);
|
|
|
|
return found;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_Print
|
|
*
|
|
* Description:
|
|
* Provides platform-specific print functionality. This function should be
|
|
* called when you want to print content suitable for console output (i.e.,
|
|
* in a large text box or on a screen). If your device/operating system is
|
|
* not supported here, you should add a port.
|
|
*
|
|
* Parameters:
|
|
* Same as printf()
|
|
*
|
|
******************************************************************************/
|
|
int SampleUtil_Print(char *fmt, ...)
|
|
{
|
|
#define MAX_BUF (8 * 1024)
|
|
va_list ap;
|
|
static char buf[MAX_BUF];
|
|
int rc;
|
|
|
|
/* Protect both the display and the static buffer with the mutex */
|
|
ithread_mutex_lock(&display_mutex);
|
|
|
|
va_start(ap, fmt);
|
|
rc = vsnprintf(buf, MAX_BUF, fmt, ap);
|
|
va_end(ap);
|
|
|
|
if (gPrintFun) {
|
|
gPrintFun(buf);
|
|
}
|
|
|
|
ithread_mutex_unlock(&display_mutex);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* SampleUtil_StateUpdate
|
|
*
|
|
* Description:
|
|
*
|
|
* Parameters:
|
|
*
|
|
******************************************************************************/
|
|
void SampleUtil_StateUpdate(const char *varName, const char *varValue,
|
|
const char *UDN, eventType type)
|
|
{
|
|
/* TBD: Add mutex here? */
|
|
if (gStateUpdateFun) {
|
|
gStateUpdateFun(varName, varValue, UDN, type);
|
|
}
|
|
}
|
|
|