/*!
 * \brief Separates the action node from the root DOM node.
 *
 * \return 0 if successful, or -1 if fails.
 */
static UPNP_INLINE int get_action_node(
	/*! [in] The root DOM node. */
	IXML_Document *TempDoc,
	/*! [in] IXML_Node name to be searched. */
	char *NodeName,
	/*! [out] Response/Output node. */
	IXML_Document **RespNode)
{
	IXML_Node *EnvpNode = NULL;
	IXML_Node *BodyNode = NULL;
	IXML_Node *ActNode = NULL;
	DOMString ActNodeName = NULL;
	const DOMString nodeName;
	int ret_code = -1;	/* error, by default */
	IXML_NodeList *nl = NULL;

	UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
		   "get_action_node(): node name =%s\n ", NodeName);
	*RespNode = NULL;
	/* Got the Envelope node here */
	EnvpNode = ixmlNode_getFirstChild((IXML_Node *) TempDoc);
	if (!EnvpNode)
		goto error_handler;
	nl = ixmlElement_getElementsByTagNameNS((IXML_Element *)EnvpNode,
						"*", "Body");
	if (!nl)
		goto error_handler;
	BodyNode = ixmlNodeList_item(nl, 0);
	if (!BodyNode)
		goto error_handler;
	/* Got action node here */
	ActNode = ixmlNode_getFirstChild(BodyNode);
	if (!ActNode)
		goto error_handler;
	/* Test whether this is the action node */
	nodeName = ixmlNode_getNodeName(ActNode);
	if (!nodeName)
		goto error_handler;
	if (!strstr(nodeName, NodeName))
		goto error_handler;
	else {
		ActNodeName = ixmlPrintNode(ActNode);
		if (!ActNodeName)
			goto error_handler;
		ret_code = ixmlParseBufferEx(ActNodeName, RespNode);
		if (ret_code != IXML_SUCCESS) {
			ixmlFreeDOMString(ActNodeName);
			ret_code = -1;
			goto error_handler;
		}
	}
	/* success */
	ret_code = 0;

error_handler:
	ixmlFreeDOMString(ActNodeName);
	if (nl)
		ixmlNodeList_free(nl);
	return ret_code;
}
示例#2
0
int genaNotifyAllExt(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	IXML_Document *PropSet)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	DOMString propertySet = NULL;

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN NOTIFY ALL EXT");

	propertySet = ixmlPrintNode((IXML_Node *)PropSet);
	if (propertySet == NULL) {
		line = __LINE__;
		ret = UPNP_E_INVALID_PARAM;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENERATED PROPERTY SET IN EXT NOTIFY: %s",
		propertySet);

	ret = genaNotifyAllCommon(device_handle, UDN, servId, propertySet);

ExitFunction:

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END NOTIFY ALL EXT, ret = %d",
		ret);

	return ret;
}
示例#3
0
/******************************************************************************
 * XMLUtil_GetNodeString
 *****************************************************************************/
char*
XMLUtil_GetNodeString (void* context, const IXML_Node* node)
{
	char* ret = NULL;
	if (node) {
		DOMString s = ixmlPrintNode (discard_const_p (IXML_Node,node));
		if (s) {
			ret = talloc_strdup (context, s);
			ixmlFreeDOMString (s);
		} else {
			ret = talloc_strdup (context, "(error)");
		}
	} else {
		ret = talloc_strdup (context, "(null)");
	}
	return ret;
}
示例#4
0
文件: upnp.cpp 项目: videolan/vlc
int MediaServer::sendActionCb( Upnp_EventType eventType,
                               void *p_event, void *p_cookie )
{
    if( eventType != UPNP_CONTROL_ACTION_COMPLETE )
        return 0;
    IXML_Document** pp_sendActionResult = (IXML_Document** )p_cookie;
    Upnp_Action_Complete *p_result = (Upnp_Action_Complete *)p_event;

    /* The only way to dup the result is to print it and parse it again */
    DOMString tmpStr = ixmlPrintNode( ( IXML_Node * ) p_result->ActionResult );
    if (tmpStr == NULL)
        return 0;

    *pp_sendActionResult = ixmlParseBuffer( tmpStr );
    ixmlFreeDOMString( tmpStr );
    return 0;
}
示例#5
0
int genaInitNotifyExt(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	IXML_Document *PropSet,
	const Upnp_SID sid)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	DOMString propertySet = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *sub = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN INITIAL NOTIFY EXT");
	
	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if( servId_copy == NULL ) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
		goto ExitFunction;
	}

	service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
	if (service == NULL) {
		line = __LINE__;
		ret = GENA_E_BAD_SERVICE;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SERVICE IN INIT NOTFY EXT: UDN %s, ServID: %s",
		UDN, servId);

	sub = GetSubscriptionSID(sid, service);
	if (sub == NULL || sub->active) {
		line = __LINE__;
		ret = GENA_E_BAD_SID;
		goto ExitFunction;
	}
	UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SUBSCRIPTION IN INIT NOTIFY EXT: SID %s", sid);
	sub->active = 1;

	if (PropSet == 0) {
		line = __LINE__;
		ret = GENA_SUCCESS;
		goto ExitFunction;
	}

	propertySet = ixmlPrintNode((IXML_Node *)PropSet);
	if (propertySet == NULL) {
		line = __LINE__;
		ret = UPNP_E_INVALID_PARAM;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENERATED PROPERTY SET IN INIT EXT NOTIFY: %s",
		propertySet);

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	/* schedule thread for initial notification */

	thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
	if (thread_struct == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
	} else {
		*reference_count = 1;
		thread_struct->servId = servId_copy;
		thread_struct->UDN = UDN_copy;
		thread_struct->headers = headers;
		thread_struct->propertySet = propertySet;
		memset(thread_struct->sid, 0, sizeof(thread_struct->sid));
		strncpy(thread_struct->sid, sid,
			sizeof(thread_struct->sid) - 1);
		thread_struct->eventKey = sub->eventKey++;
		thread_struct->reference_count = reference_count;
		thread_struct->device_handle = device_handle;

		TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct);
		TPJobSetFreeFunction(&job, (free_routine)free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);

		ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		if (ret != 0) {
			if (ret == EOUTOFMEM) {
				line = __LINE__;
				ret = UPNP_E_OUTOF_MEMORY;
			}
		} else {
			line = __LINE__;
			ret = GENA_SUCCESS;
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS || PropSet == 0) {
		free(thread_struct);
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END INITIAL NOTIFY EXT, ret = %d",
		ret);

	return ret;
}
示例#6
0
/****************************************************************************
*	Function :	get_response_value
*
*	Parameters :
*			IN http_message_t* hmsg :	HTTP response message
*			IN int code :	return code in the HTTP response
*			IN char*name :	name of the action
*			OUT int *upnp_error_code :	UPnP error code
*			OUT IXML_Node ** action_value :	SOAP response node 
*			OUT DOMString * str_value : state varible value ( in the case of 
*							querry state variable request)	
*
*	Description :	This function handles the response coming back from the 
*		device. This function parses the response and gives back the SOAP 
*		response node.
*
*	Return : int
*		return the type of the SOAP message if successful else returns 
*	appropriate error.
*
*	Note :
****************************************************************************/
static int
get_response_value( IN http_message_t * hmsg,
                    IN int code,
                    IN char *name,
                    OUT int *upnp_error_code,
                    OUT IXML_Node ** action_value,
                    OUT DOMString * str_value )
{
    IXML_Node *node = NULL;
    IXML_Node *root_node = NULL;
    IXML_Node *error_node = NULL;
    IXML_Document *doc = NULL;
    char *node_str = NULL;
    const char *temp_str = NULL;
    DOMString error_node_str = NULL;
    int err_code;
    xboolean done = FALSE;
    char *names[5];
    const DOMString nodeValue;

    err_code = UPNP_E_BAD_RESPONSE; // default error

    // only 200 and 500 status codes are relevant
    if( ( hmsg->status_code != HTTP_OK &&
          hmsg->status_code != HTTP_INTERNAL_SERVER_ERROR ) ||
        !has_xml_content_type( hmsg ) ) {

        goto error_handler;
    }

    if( ixmlParseBufferEx( hmsg->entity.buf, &doc ) != IXML_SUCCESS ) {

        goto error_handler;
    }

    root_node = ixmlNode_getFirstChild( ( IXML_Node * ) doc );
    if( root_node == NULL ) {

        goto error_handler;
    }

    if( code == SOAP_ACTION_RESP ) {
        //
        // try reading soap action response
        //
        assert( action_value != NULL );

        *action_value = NULL;

        names[0] = "Envelope";
        names[1] = "Body";
        names[2] = name;
        if( dom_find_deep_node( names, 3, root_node, &node ) ==
            UPNP_E_SUCCESS ) {
            node_str = ixmlPrintNode( node );
            if( node_str == NULL ) {
                err_code = UPNP_E_OUTOF_MEMORY;
                goto error_handler;
            }

            if( ixmlParseBufferEx( node_str,
                                   ( IXML_Document ** ) action_value ) !=
                IXML_SUCCESS ) {
                err_code = UPNP_E_BAD_RESPONSE;
                goto error_handler;
            }

            err_code = SOAP_ACTION_RESP;
            done = TRUE;
        }
    } else if( code == SOAP_VAR_RESP ) {
        // try reading var response
        assert( str_value != NULL );
        *str_value = NULL;

        names[0] = "Envelope";
        names[1] = "Body";
        names[2] = "QueryStateVariableResponse";
        names[3] = "return";
        if( dom_find_deep_node( names, 4, root_node, &node )
            == UPNP_E_SUCCESS ) {
            nodeValue = get_node_value( node );
            if( nodeValue == NULL ) {
                goto error_handler;
            }

            *str_value = ixmlCloneDOMString( nodeValue );
            err_code = SOAP_VAR_RESP;
            done = TRUE;
        }
    }

    if( !done ) {
        // not action or var resp; read error code and description
        *str_value = NULL;

        names[0] = "Envelope";
        names[1] = "Body";
        names[2] = "Fault";
        names[3] = "detail";
        names[4] = "UPnPError";
        if( dom_find_deep_node( names, 5, root_node, &error_node )
            != UPNP_E_SUCCESS ) {
            goto error_handler;
        }

        if( dom_find_node( "errorCode", error_node, &node )
            != UPNP_E_SUCCESS ) {
            goto error_handler;
        }

        temp_str = get_node_value( node );
        if( temp_str == NULL ) {
            goto error_handler;
        }

        *upnp_error_code = atoi( temp_str );
        if( *upnp_error_code > 400 ) {
            err_code = *upnp_error_code;
            goto error_handler; // bad SOAP error code
        }

        if( code == SOAP_VAR_RESP ) {
            if( dom_find_node( "errorDescription", error_node, &node )
                != UPNP_E_SUCCESS ) {
                goto error_handler;
            }

            nodeValue = get_node_value( node );
            if( nodeValue == NULL ) {
                goto error_handler;
            }
            *str_value = ixmlCloneDOMString( nodeValue );
            if( *str_value == NULL ) {
                goto error_handler;
            }
            err_code = SOAP_VAR_RESP_ERROR;
        }

        else if( code == SOAP_ACTION_RESP ) {
            error_node_str = ixmlPrintNode( error_node );
            if( error_node_str == NULL ) {
                err_code = UPNP_E_OUTOF_MEMORY;
                goto error_handler;
            }

            if( ixmlParseBufferEx( error_node_str,
                                   ( IXML_Document ** ) action_value ) !=
                IXML_SUCCESS ) {
                err_code = UPNP_E_BAD_RESPONSE;

                goto error_handler;
            }
            err_code = SOAP_ACTION_RESP_ERROR;
        }
    }

  error_handler:

    ixmlDocument_free( doc );
    ixmlFreeDOMString( node_str );
    ixmlFreeDOMString( error_node_str );
    return err_code;
}
示例#7
0
    int xml_end_len;
    int action_str_len;

    *response_node = NULL;      // init

    err_code = UPNP_E_OUTOF_MEMORY; // default error

    DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
                         "Inside SoapSendAction():" );
         )
        // init
        membuffer_init( &request );
    membuffer_init( &responsename );

    // print action
    action_str = ixmlPrintNode( ( IXML_Node * ) action_node );
    if( action_str == NULL ) {
        goto error_handler;
    }
    // get action name
    if( get_action_name( action_str, &name ) != 0 ) {
        err_code = UPNP_E_INVALID_ACTION;
        goto error_handler;
    }
    // parse url
    if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) {
        err_code = UPNP_E_INVALID_URL;
        goto error_handler;
    }

    DBGONLY( UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
示例#8
0
/*!
 * \brief Sends the SOAP action response.
 */
static UPNP_INLINE void send_action_response(
	/*! [in] Socket info. */
	SOCKINFO *info,
	/*! [in] The response document. */
	IXML_Document *action_resp,
	/*! [in] Action request document. */
	http_message_t *request)
{
	char *xml_response = NULL;
	membuffer headers;
	int major, minor;
	int err_code;
	off_t content_length;
	int ret_code;
	int timeout_secs = SOAP_TIMEOUT;
	static const char *start_body =
		"<?xml version=\"1.0\"?>"
		"<s:Envelope xmlns:s=\"http://schemas.xmlsoap."
		"org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap."
		"org/soap/encoding/\"><s:Body>\n";
	static const char *end_body = "</s:Body> </s:Envelope>";

	/* init */
	http_CalcResponseVersion(request->major_version, request->minor_version,
		&major, &minor);
	membuffer_init(&headers);
	err_code = UPNP_E_OUTOF_MEMORY;	/* one error only */
	/* get xml */
	xml_response = ixmlPrintNode((IXML_Node *) action_resp);
	if (!xml_response)
		goto error_handler;
	content_length = (off_t)(strlen(start_body) + strlen(xml_response) +
		strlen(end_body));
	/* make headers */
	if (http_MakeMessage(&headers, major, minor,
			"RNsDsSXcc",
			HTTP_OK,	/* status code */
			content_length,
			ContentTypeHeader,
			"EXT:\r\n", X_USER_AGENT) != 0) {
		goto error_handler;
	}
	/* send whole msg */
	ret_code = http_SendMessage(
		info, &timeout_secs, "bbbb",
		headers.buf, headers.length,
		start_body, strlen(start_body),
		xml_response, strlen(xml_response),
		end_body, strlen(end_body));
	if (ret_code != 0) {
		UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
			   "Failed to send response: err code = %d\n",
			   ret_code);
	}
	err_code = 0;

error_handler:
	ixmlFreeDOMString(xml_response);
	membuffer_destroy(&headers);
	if (err_code != 0) {
		/* only one type of error to worry about - out of mem */
		send_error_response(info, SOAP_ACTION_FAILED, "Out of memory",
			request);
	}
}
示例#9
0
BOOL CVCAMetaParserIXML::ParseObjects( )
{
	IXML_NodeList *pNodeList = ixmlDocument_getElementsByTagName(m_pDOMDoc, _XML_OBJECTS);
	if( pNodeList ) {
		IXML_Node *pObjectsNode, *pObjectNode;
		IXML_NodeList *pObjectNodeList;

		m_vcaObjects.ulTotalObject = 0;

		pObjectsNode = pNodeList->nodeItem;

	//	TRACE(ixmlPrintNode(pObjectsNode));
		//pObjectNode = ixmlNode_getFirstChild(pObjectsNode);
		pObjectNodeList = ixmlElement_getElementsByTagName((IXML_Element*)pObjectsNode, _XML_OBJECT);
#if 0
		if(pObjectNodeList) {
			pObjectNode = pObjectNodeList->nodeItem;
			while(pObjectNode) {
				TRACE("=====================================\n");
				TRACE(ixmlPrintNode(pObjectNode));
				pObjectNode = pObjectNode->nextSibling;
				//pObjectNode = pObjectNodeList->next;
			}
		}
#endif
		VCA5_PACKET_OBJECT	vcaObj;
		ULONG ulVal = 0;
		int iVal = 0;
		if(pObjectNodeList) {
			pObjectNode = pObjectNodeList->nodeItem;

			while(pObjectNode) {
				memset( &vcaObj, 0, sizeof( vcaObj ) );

				ulVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_ID);
				if(ulVal != -1) vcaObj.ulId = ulVal;

				ulVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_CH);
				if(ulVal != -1) vcaObj.ulCalibHeight = ulVal;

				ulVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_CS);
				if(ulVal != -1) vcaObj.ulCalibSpeed = ulVal;

				ulVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_CA);
				if(ulVal != -1) vcaObj.ulCalibArea = ulVal;

				iVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_CLS);
				if(ulVal != -1) vcaObj.iClassificationId = iVal;
				else vcaObj.iClassificationId = -2;  // unknown
				
				CHAR colSigs[VCA5_APP_PALETTE_SIZE * 2] = { 0, };
				ulVal = (ULONG)GetNodeValueString(pObjectNode, _XML_COLSIG, colSigs);
				if(ulVal != FALSE) memcpy(vcaObj.colSigs, colSigs, sizeof( vcaObj.colSigs ) );

				// Bounding box
				IXML_NodeList *pBBOXNodeList = ixmlElement_getElementsByTagName((IXML_Element*)pObjectNode, _XML_BB);
				if(pBBOXNodeList) {
					ParseBBox( pBBOXNodeList->nodeItem, &vcaObj.bBox );
					ixmlNodeList_free(pBBOXNodeList);
				}

				// Trail
				IXML_NodeList *pTrailNodeList = ixmlElement_getElementsByTagName((IXML_Element*)pObjectNode, _XML_TRAIL);
				if( pTrailNodeList ) {
					ParseTrail( pTrailNodeList, &vcaObj.trail );
					ixmlNodeList_free(pTrailNodeList);
				}

				// Flags
				ulVal = (ULONG)GetNodeValueInt(pObjectNode, _XML_FLAGS);
				if(ulVal != -1) vcaObj.ulFlags = ulVal;

				m_vcaObjects.Objects[m_vcaObjects.ulTotalObject]  = vcaObj;
				m_vcaObjects.ulTotalObject++;

				pObjectNode = pObjectNode->nextSibling;
			}
			ixmlNodeList_free(pObjectNodeList);
		//	TRACE("# Objects [%2d]\n", m_vcaObjects.ulTotalObject);
		}

		ixmlNodeList_free(pNodeList);
	}

	return TRUE;
}
示例#10
0
/*
	Function:Prints a callback event type as a string;
	INPUT:
		S -- The callback event;
	SUCCESS:0;
	ERROR:-1;		
*/
int
PrintEvent( IN Upnp_EventType EventType,
                       IN void *Event )
{

    ithread_mutex_lock( &display_mutex );

    SA_Print
        ( "\n\n\n======================================================================\n" );
    SA_Print
        ( "----------------------------------------------------------------------\n" );
    PrintEventType( EventType );

    switch ( EventType ) {

            /*
               SSDP 
             */
        case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
        case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
        case UPNP_DISCOVERY_SEARCH_RESULT:
            {
                struct Upnp_Discovery *d_event =
                    ( struct Upnp_Discovery * )Event;

                SA_Print( "ErrCode     =  %d\n",
                                  d_event->ErrCode );
                SA_Print( "Expires     =  %d\n",
                                  d_event->Expires );
                SA_Print( "DeviceId    =  %s\n",
                                  d_event->DeviceId );
                SA_Print( "DeviceType  =  %s\n",
                                  d_event->DeviceType );
                SA_Print( "ServiceType =  %s\n",
                                  d_event->ServiceType );
                SA_Print( "ServiceVer  =  %s\n",
                                  d_event->ServiceVer );
                SA_Print( "Location    =  %s\n",
                                  d_event->Location );
	

                SA_Print( "OS          =  %s\n", d_event->Os );
                SA_Print( "Ext         =  %s\n", d_event->Ext );
	
		sem_post(&ServerSem);

            }
            break;

        case UPNP_DISCOVERY_SEARCH_TIMEOUT:
            // Nothing to print out here
            break;

            /*
               SOAP 
             */
        case UPNP_CONTROL_ACTION_REQUEST:
            {
                struct Upnp_Action_Request *a_event =
                    ( struct Upnp_Action_Request * )Event;
                char *xmlbuff = NULL;

                SA_Print( "ErrCode     =  %d\n",
                                  a_event->ErrCode );
                SA_Print( "ErrStr      =  %s\n", a_event->ErrStr );
                SA_Print( "ActionName  =  %s\n",
                                  a_event->ActionName );
                SA_Print( "UDN         =  %s\n", a_event->DevUDN );
                SA_Print( "ServiceID   =  %s\n",
                                  a_event->ServiceID );
                if( a_event->ActionRequest ) {
                    xmlbuff = ixmlPrintNode( ( IXML_Node * ) a_event->ActionRequest );	
			
                    if( xmlbuff )
                        SA_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SA_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) {
                    xmlbuff = ixmlPrintNode( ( IXML_Node * ) a_event->ActionResult );
                    if( xmlbuff )
                        SA_Print( "ActResult   =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SA_Print( "ActResult   =  (null)\n" );
                }
            }
            break;

        case UPNP_CONTROL_ACTION_COMPLETE:
            {
                struct Upnp_Action_Complete *a_event =
                    ( struct Upnp_Action_Complete * )Event;
                char *xmlbuff = NULL;

                SA_Print( "ErrCode     =  %d\n",
                                  a_event->ErrCode );
                SA_Print( "CtrlUrl     =  %s\n",
                                  a_event->CtrlUrl );

                if( a_event->ActionRequest ) {
                    xmlbuff = ixmlPrintNode( ( IXML_Node * ) a_event->ActionRequest );
                    if( xmlbuff )
                        SA_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SA_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) 
		{
		    xmlbuff = ixmlPrintNode( ( IXML_Node * ) a_event->ActionResult );
                    if( xmlbuff )
                        SA_Print( "ActResult   =  %s\n", xmlbuff );

		if(strncmp(NowCommand,"Browse",6) == 0)
		{

			FNode *Now = (FNode *)malloc(sizeof(FNode));

			FNode *Last = NowNode;

			NowNode -> LeftChild = Now;		

			IXML_Document *document = ixmlParseBuffer(XMLP_GetFirstDocumentItem(a_event->ActionResult,"Result"));

			IXML_NodeList *ContainerList = ixmlElement_getElementsByTagName( ( IXML_Element * ) document, "container" );

			IXML_Node *ContainerNode = ixmlNodeList_item(ContainerList,0);

			IXML_NodeList *FileList = ixmlElement_getElementsByTagName( ( IXML_Element * ) document, "item" );

			IXML_Node *FileNode = ixmlNodeList_item(FileList,0);

			int ContainerLength = ixmlNodeList_length(ContainerList);

			int FileLength = ixmlNodeList_length(FileList);
		
			if(ContainerLength)
			{

				int i=0;
	
				for(i=0;i<ContainerLength;i++)
				{		

					char *Container_id = ixmlElement_getAttribute(( IXML_Element * ) ContainerNode,"id");

					IXML_NodeList *Title = ixmlElement_getElementsByTagName( ( IXML_Element * ) ContainerNode, "dc:title" );
	
					IXML_Node *TitleNode = ixmlNodeList_item(Title,0);

					TitleNode= ixmlNode_getFirstChild(TitleNode);

					char *TitleName = strdup(ixmlNode_getNodeValue(TitleNode));

					SA_Print("%s %s\n", Container_id,TitleName);

					Now -> Type = 0;

					strcpy(Now -> Name,TitleName);

					strcpy(Now -> Url,Container_id);

					Now -> LeftChild = NULL;
			
					Now -> Brother = NULL;

					Now -> Brother = (FNode *)malloc(sizeof(FNode));

					Last = Now;

					Now = Now -> Brother;

					ContainerNode = ixmlNode_getNextSibling(ContainerNode);
			
				}

			}

			if(FileLength)
			{	

				int j=0;	

				for(j=0;j<FileLength;j++)
				{		

					IXML_NodeList *Path = ixmlElement_getElementsByTagName( ( IXML_Element * ) FileNode, "res" );
	
					IXML_Node *PathNode = ixmlNodeList_item(Path,0);

					PathNode= ixmlNode_getFirstChild(PathNode);

					char *PathName = strdup(ixmlNode_getNodeValue(PathNode));

					IXML_NodeList *Title = ixmlElement_getElementsByTagName( ( IXML_Element * ) FileNode, "dc:title" );
	
					IXML_Node *TitleNode = ixmlNodeList_item(Title,0);

					TitleNode= ixmlNode_getFirstChild(TitleNode);

					char *TitleName = strdup(ixmlNode_getNodeValue(TitleNode));

					SA_Print( "%s %s\n", PathName,TitleName);

					Now -> Type = 1;

					strcpy(Now -> Name,TitleName);

					strcpy(Now -> Url,PathName);

					Now -> LeftChild = NULL;
			
					Now -> Brother = NULL;

					Now -> Brother = (FNode *)malloc(sizeof(FNode));

					Last = Now;	

					Now = Now -> Brother;
			
					FileNode = ixmlNode_getNextSibling(FileNode);
			
				}
					
			}

			Last -> Brother = NULL;

			Last -> LeftChild = NULL;

			free(Now);

			Now = NULL;


		}

                if( xmlbuff )
	        {
                      	ixmlFreeDOMString( xmlbuff );
                   	xmlbuff = NULL;
                }


		}
		else 
		{
                    SA_Print( "ActResult   =  (null)\n" );
                }

		sem_post(&BrowseSem);

            }
            break;

            /*
               GENA 
             */
        case UPNP_EVENT_SUBSCRIPTION_REQUEST:
            {
                struct Upnp_Subscription_Request *sr_event =
                    ( struct Upnp_Subscription_Request * )Event;

                SA_Print( "ServiceID   =  %s\n",
                                  sr_event->ServiceId );
                SA_Print( "UDN         =  %s\n", sr_event->UDN );
                SA_Print( "SID         =  %s\n", sr_event->Sid );
            }
            break;

        case UPNP_EVENT_RECEIVED:
            break;

        case UPNP_EVENT_RENEWAL_COMPLETE:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SA_Print( "SID         =  %s\n", es_event->Sid );
                SA_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SA_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

        case UPNP_EVENT_SUBSCRIBE_COMPLETE:
        case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SA_Print( "SID         =  %s\n", es_event->Sid );
                SA_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SA_Print( "PublisherURL=  %s\n",
                                  es_event->PublisherUrl );
                SA_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

        case UPNP_EVENT_AUTORENEWAL_FAILED:
        case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SA_Print( "SID         =  %s\n", es_event->Sid );
                SA_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SA_Print( "PublisherURL=  %s\n",
                                  es_event->PublisherUrl );
                SA_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;
	default:
	    break;
    }
    SA_Print
        ( "----------------------------------------------------------------------\n" );
    SA_Print
        ( "======================================================================\n\n\n\n" );

    ithread_mutex_unlock( &display_mutex );
    return ( 0 );
}
示例#11
0
char* xmldb_getDump()
{
    return ixmlPrintNode(ixmlDocument_getNode(_storage));
}
示例#12
0
/** Prints contents of XML node to debug log. */
static void printXMLContents(IXML_Node* node, const char* title)
{
    DOMString str = ixmlPrintNode(node);
    log_debug("\n%s:\n%s",title, str);
    ixmlFreeDOMString(str);
}
示例#13
0
char* xmldb_get(const char* href, int* slashFlag)
{
    return ixmlPrintNode(getNodeByHref(_storage, href, slashFlag));
}
示例#14
0
/****************************************************************************
*	Function :	get_action_node
*
*	Parameters :
*		IN IXML_Document *TempDoc :	The root DOM node.
*		IN char *NodeName :	IXML_Node name to be searched.
*		OUT IXML_Document ** RespNode :	Response/Output node.
*
*	Description :	This function separates the action node from
*	the root DOM node.
*
*	Return :	static UPNP_INLINE int
*		0 if successful, or -1 if fails.
*
*	Note :
****************************************************************************/
static UPNP_INLINE int
get_action_node( IN IXML_Document * TempDoc,
                 IN char *NodeName,
                 OUT IXML_Document ** RespNode )
{
    IXML_Node *EnvpNode = NULL;
    IXML_Node *BodyNode = NULL;
    IXML_Node *ActNode = NULL;
    DOMString ActNodeName = NULL;
    const DOMString nodeName;
    int ret_code = -1;          // error, by default
    IXML_NodeList *nl = NULL;

    UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
                "get_action_node(): node name =%s\n ", NodeName );

    *RespNode = NULL;

    // Got the Envelope node here
    EnvpNode = ixmlNode_getFirstChild( ( IXML_Node * ) TempDoc );
    if( EnvpNode == NULL ) {
        goto error_handler;
    }

    nl = ixmlElement_getElementsByTagNameNS( ( IXML_Element * ) EnvpNode,
            "*", "Body" );

    if( nl == NULL ) {
        goto error_handler;
    }

    BodyNode = ixmlNodeList_item( nl, 0 );

    if( BodyNode == NULL ) {
        goto error_handler;
    }
    // Got action node here
    ActNode = ixmlNode_getFirstChild( BodyNode );
    if( ActNode == NULL ) {
        goto error_handler;
    }
    //Test whether this is the action node
    nodeName = ixmlNode_getNodeName( ActNode );
    if( nodeName == NULL ) {
        goto error_handler;
    }

    if( strstr( nodeName, NodeName ) == NULL ) {
        goto error_handler;
    } else {
        ActNodeName = ixmlPrintNode( ActNode );
        if( ActNodeName == NULL ) {
            goto error_handler;
        }

        ret_code = ixmlParseBufferEx( ActNodeName, RespNode );
        if( ret_code != IXML_SUCCESS ) {
            ixmlFreeDOMString( ActNodeName );
            ret_code = -1;
            goto error_handler;
        }
    }

    ret_code = 0;               // success

error_handler:

    ixmlFreeDOMString( ActNodeName );

    if( nl )
        ixmlNodeList_free( nl );
    return ret_code;
}
示例#15
0
int genaNotifyAllExt(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	IXML_Document *PropSet)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	DOMString propertySet = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *finger = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN NOTIFY ALL EXT");

	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if( servId_copy == NULL ) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	propertySet = ixmlPrintNode((IXML_Node *)PropSet);
	if (propertySet == NULL) {
		line = __LINE__;
		ret = UPNP_E_INVALID_PARAM;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENERATED PROPERTY SET IN EXT NOTIFY: %s",
		propertySet);

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
	} else {
		service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
		if (service != NULL) {
			finger = GetFirstSubscription(service);
			while (finger) {
				thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
				if (thread_struct == NULL) {
					line = __LINE__;
					ret = UPNP_E_OUTOF_MEMORY;
					break;
				}

				(*reference_count)++;
				thread_struct->reference_count = reference_count;
				thread_struct->UDN = UDN_copy;
				thread_struct->servId = servId_copy;
				thread_struct->headers = headers;
				thread_struct->propertySet = propertySet;
				memset(thread_struct->sid, 0,
					sizeof(thread_struct->sid));
				strncpy(thread_struct->sid, finger->sid,
					sizeof(thread_struct->sid) - 1);
				thread_struct->eventKey = finger->eventKey++;
				thread_struct->device_handle = device_handle;
				/* if overflow, wrap to 1 */
				if (finger->eventKey < 0) {
					finger->eventKey = 1;
				}

				TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct);
				TPJobSetFreeFunction(&job, (free_routine)free_notify_struct);
				TPJobSetPriority(&job, MED_PRIORITY);
				ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL);
				if (ret != 0) {
					line = __LINE__;
					if (ret == EOUTOFMEM) {
						line = __LINE__;
						ret = UPNP_E_OUTOF_MEMORY;
					}
					break;
				}

				finger = GetNextSubscription(service, finger);
			}
		} else {
			line = __LINE__;
			ret = GENA_E_BAD_SERVICE;
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS || *reference_count == 0) {
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END NOTIFY ALL EXT, ret = %d",
		ret);

	return ret;
}
示例#16
0
int SampleUtil_PrintEvent(Upnp_EventType EventType, 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: {
		struct Upnp_Discovery *d_event = (struct Upnp_Discovery *)Event;

		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(d_event->ErrCode), d_event->ErrCode);
		SampleUtil_Print("Expires     =  %d\n",  d_event->Expires);
		SampleUtil_Print("DeviceId    =  %s\n",  d_event->DeviceId);
		SampleUtil_Print("DeviceType  =  %s\n",  d_event->DeviceType);
		SampleUtil_Print("ServiceType =  %s\n",  d_event->ServiceType);
		SampleUtil_Print("ServiceVer  =  %s\n",  d_event->ServiceVer);
		SampleUtil_Print("Location    =  %s\n",  d_event->Location);
		SampleUtil_Print("OS          =  %s\n",  d_event->Os);
		SampleUtil_Print("Ext         =  %s\n",  d_event->Ext);
		break;
	}
	case UPNP_DISCOVERY_SEARCH_TIMEOUT:
		/* Nothing to print out here */
		break;
	/* SOAP */
	case UPNP_CONTROL_ACTION_REQUEST: {
		struct Upnp_Action_Request *a_event =
			(struct Upnp_Action_Request *)Event;
		char *xmlbuff = NULL;

		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(a_event->ErrCode), a_event->ErrCode);
		SampleUtil_Print("ErrStr      =  %s\n", a_event->ErrStr);
		SampleUtil_Print("ActionName  =  %s\n", a_event->ActionName);
		SampleUtil_Print("UDN         =  %s\n", a_event->DevUDN);
		SampleUtil_Print("ServiceID   =  %s\n", a_event->ServiceID);
		if (a_event->ActionRequest) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->ActionRequest);
			if (xmlbuff) {
				SampleUtil_Print("ActRequest  =  %s\n", xmlbuff);
				ixmlFreeDOMString(xmlbuff);
			}
			xmlbuff = NULL;
		} else {
			SampleUtil_Print("ActRequest  =  (null)\n");
		}
		if (a_event->ActionResult) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->ActionResult);
			if (xmlbuff) {
				SampleUtil_Print("ActResult   =  %s\n", xmlbuff);
				ixmlFreeDOMString(xmlbuff);
			}
			xmlbuff = NULL;
		} else {
			SampleUtil_Print("ActResult   =  (null)\n");
		}
		break;
	}
	case UPNP_CONTROL_ACTION_COMPLETE: {
		struct Upnp_Action_Complete *a_event =
			(struct Upnp_Action_Complete *)Event;
		char *xmlbuff = NULL;

		SampleUtil_Print("ErrCode     =  %s(%d)\n",  
			UpnpGetErrorMessage(a_event->ErrCode), a_event->ErrCode);
		SampleUtil_Print("CtrlUrl     =  %s\n", a_event->CtrlUrl);
		if (a_event->ActionRequest) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->ActionRequest);
			if (xmlbuff) {
				SampleUtil_Print("ActRequest  =  %s\n", xmlbuff);
				ixmlFreeDOMString(xmlbuff);
			}
			xmlbuff = NULL;
		} else {
			SampleUtil_Print("ActRequest  =  (null)\n");
		}
		if (a_event->ActionResult) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->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: {
		struct Upnp_State_Var_Request *sv_event =
			(struct Upnp_State_Var_Request *)Event;

		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(sv_event->ErrCode), sv_event->ErrCode);
		SampleUtil_Print("ErrStr      =  %s\n", sv_event->ErrStr);
		SampleUtil_Print("UDN         =  %s\n", sv_event->DevUDN);
		SampleUtil_Print("ServiceID   =  %s\n", sv_event->ServiceID);
		SampleUtil_Print("StateVarName=  %s\n", sv_event->StateVarName);
		SampleUtil_Print("CurrentVal  =  %s\n", sv_event->CurrentVal);
		break;
	}
	case UPNP_CONTROL_GET_VAR_COMPLETE: {
		struct Upnp_State_Var_Complete *sv_event =
			(struct Upnp_State_Var_Complete *)Event;

		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(sv_event->ErrCode), sv_event->ErrCode);
		SampleUtil_Print("CtrlUrl     =  %s\n", sv_event->CtrlUrl);
		SampleUtil_Print("StateVarName=  %s\n", sv_event->StateVarName);
		SampleUtil_Print("CurrentVal  =  %s\n", sv_event->CurrentVal);
		break;
	}
	/* GENA */
	case UPNP_EVENT_SUBSCRIPTION_REQUEST: {
		struct Upnp_Subscription_Request *sr_event =
			(struct Upnp_Subscription_Request *)Event;

		SampleUtil_Print("ServiceID   =  %s\n", sr_event->ServiceId);
		SampleUtil_Print("UDN         =  %s\n", sr_event->UDN);
		SampleUtil_Print("SID         =  %s\n", sr_event->Sid);
		break;
	}
	case UPNP_EVENT_RECEIVED: {
		struct Upnp_Event *e_event = (struct Upnp_Event *)Event;
		char *xmlbuff = NULL;

		SampleUtil_Print("SID         =  %s\n", e_event->Sid);
		SampleUtil_Print("EventKey    =  %d\n",	e_event->EventKey);
		xmlbuff = ixmlPrintNode((IXML_Node *)e_event->ChangedVariables);
		SampleUtil_Print("ChangedVars =  %s\n", xmlbuff);
		ixmlFreeDOMString(xmlbuff);
		xmlbuff = NULL;
		break;
	}
	case UPNP_EVENT_RENEWAL_COMPLETE: {
		struct Upnp_Event_Subscribe *es_event =
			(struct Upnp_Event_Subscribe *)Event;

		SampleUtil_Print("SID         =  %s\n", es_event->Sid);
		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		SampleUtil_Print("TimeOut     =  %d\n", es_event->TimeOut);
		break;
	}
	case UPNP_EVENT_SUBSCRIBE_COMPLETE:
	case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: {
		struct Upnp_Event_Subscribe *es_event =
			(struct Upnp_Event_Subscribe *)Event;

		SampleUtil_Print("SID         =  %s\n", es_event->Sid);
		SampleUtil_Print("ErrCode     =  %s(%d)\n",
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		SampleUtil_Print("PublisherURL=  %s\n", es_event->PublisherUrl);
		SampleUtil_Print("TimeOut     =  %d\n", es_event->TimeOut);
		break;
	}
	case UPNP_EVENT_AUTORENEWAL_FAILED:
	case UPNP_EVENT_SUBSCRIPTION_EXPIRED: {
		struct Upnp_Event_Subscribe *es_event =
			(struct Upnp_Event_Subscribe *)Event;

		SampleUtil_Print("SID         =  %s\n", es_event->Sid);
		SampleUtil_Print("ErrCode     =  %s(%d)\n",  
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		SampleUtil_Print("PublisherURL=  %s\n", es_event->PublisherUrl);
		SampleUtil_Print("TimeOut     =  %d\n", es_event->TimeOut);
		break;
	}
	}
	SampleUtil_Print(
		"----------------------------------------------------------------------\n"
		"======================================================================\n"
		"\n\n\n");

	ithread_mutex_unlock(&display_mutex);

	return 0;
}
示例#17
0
/****************************************************************************
*	Function :	SoapSendActionEx
*
*	Parameters :
*		IN char* action_url :	device contrl URL 
*		IN char *service_type :	device service type
		IN IXML_Document *Header: Soap header
*		IN IXML_Document *action_node : SOAP action node ( SOAP body)	
*		OUT IXML_Document **response_node :	SOAP response node
*
*	Description :	This function is called by UPnP API to send the SOAP 
*		action request and waits till it gets the response from the device
*		pass the response to the API layer. This action is similar to the 
*		the SoapSendAction with only difference that it allows users to 
*		pass the SOAP header along the SOAP body ( soap action request)
*
*	Return :	int
*		returns UPNP_E_SUCCESS if successful else returns appropriate error
*	Note :
****************************************************************************/
int SoapSendActionEx(
	IN char *action_url,
	IN char *service_type,
	IN IXML_Document * header,
	IN IXML_Document * action_node,
	OUT IXML_Document ** response_node )
{
    char *xml_header_str = NULL;
    char *action_str = NULL;
    memptr name;
    membuffer request;
    membuffer responsename;
    int err_code;
    int ret_code;
    http_parser_t response;
    uri_type url;
    int upnp_error_code;
    char *upnp_error_str;
    int got_response = FALSE;
    const char *xml_start =
        "<s:Envelope "
        "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n";
    const char *xml_header_start =
        "<s:Header>\r\n";
    const char *xml_header_end =
        "</s:Header>\r\n";
    const char *xml_body_start =
        "<s:Body>";
    const char *xml_end =
        "</s:Body>\r\n"
        "</s:Envelope>\r\n";
    size_t xml_start_len;
    size_t xml_header_start_len;
    size_t xml_header_str_len;
    size_t xml_header_end_len;
    size_t xml_body_start_len;
    size_t action_str_len;
    size_t xml_end_len;
    off_t content_length;

    *response_node = NULL;      /* init */

    err_code = UPNP_E_OUTOF_MEMORY; /* default error */

    UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
        "Inside SoapSendActionEx():" );
    /* init */
    membuffer_init( &request );
    membuffer_init( &responsename );

    /* header string */
    xml_header_str = ixmlPrintNode( ( IXML_Node * ) header );
    if( xml_header_str == NULL ) {
        goto error_handler;
    }
    /* print action */
    action_str = ixmlPrintNode( ( IXML_Node * ) action_node );
    if( action_str == NULL ) {
        goto error_handler;
    }
    /* get action name */
    if( get_action_name( action_str, &name ) != 0 ) {
        err_code = UPNP_E_INVALID_ACTION;
        goto error_handler;
    }
    /* parse url */
    if( http_FixStrUrl( action_url, strlen( action_url ), &url ) != 0 ) {
        err_code = UPNP_E_INVALID_URL;
        goto error_handler;
    }

    UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
        "path=%.*s, hostport=%.*s\n",
        (int)url.pathquery.size,
        url.pathquery.buff,
        (int)url.hostport.text.size,
        url.hostport.text.buff );

    xml_start_len = strlen( xml_start );
    xml_body_start_len = strlen( xml_body_start );
    xml_end_len = strlen( xml_end );
    action_str_len = strlen( action_str );

    xml_header_start_len = strlen( xml_header_start );
    xml_header_end_len = strlen( xml_header_end );
    xml_header_str_len = strlen( xml_header_str );

    /* make request msg */
    request.size_inc = 50;
    content_length = (off_t)(xml_start_len + xml_header_start_len +
	xml_header_str_len + xml_header_end_len +
        xml_body_start_len + action_str_len + xml_end_len);
    if (http_MakeMessage(
        &request, 1, 1,
        "q" "N" "s" "sssbsc" "Uc" "b" "b" "b" "b" "b" "b" "b",
        SOAPMETHOD_POST, &url,
        content_length,
        ContentTypeHeader,
        "SOAPACTION: \"", service_type, "#", name.buf, name.length, "\"",
        xml_start, xml_start_len,
        xml_header_start, xml_header_start_len,
        xml_header_str, xml_header_str_len,
        xml_header_end, xml_header_end_len,
        xml_body_start, xml_body_start_len,
        action_str, action_str_len,
        xml_end, xml_end_len ) != 0 ) {
        goto error_handler;
    }

    ret_code = soap_request_and_response( &request, &url, &response );
    got_response = TRUE;
    if( ret_code != UPNP_E_SUCCESS ) {
        err_code = ret_code;
        goto error_handler;
    }

    if( membuffer_append( &responsename, name.buf, name.length ) != 0 ||
        membuffer_append_str( &responsename, "Response" ) != 0 ) {
        goto error_handler;
    }
    /* get action node from the response */
    ret_code = get_response_value( &response.msg, SOAP_ACTION_RESP,
                                   responsename.buf, &upnp_error_code,
                                   ( IXML_Node ** ) response_node,
                                   &upnp_error_str );

    if( ret_code == SOAP_ACTION_RESP ) {
        err_code = UPNP_E_SUCCESS;
    } else if( ret_code == SOAP_ACTION_RESP_ERROR ) {
        err_code = upnp_error_code;
    } else {
        err_code = ret_code;
    }

  error_handler:

    ixmlFreeDOMString( action_str );
    ixmlFreeDOMString( xml_header_str );
    membuffer_destroy( &request );
    membuffer_destroy( &responsename );
    if( got_response ) {
        httpmsg_destroy( &response.msg );
    }

    return err_code;
}