예제 #1
0
/*!
 * \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
/************************************************************************
*	Function :	freeService
*
*	Parameters :
*		service_info *in ;	service information that is to be freed
*
*	Description :	Free's memory allocated for the various components 
*		of the service entry in the service table.
*
*	Return : void ;
*
*	Note :
************************************************************************/
void freeService( service_info * in )
{
    if( in ) {
        if( in->serviceType )
            ixmlFreeDOMString( in->serviceType );

        if( in->serviceId )
            ixmlFreeDOMString( in->serviceId );

        if( in->SCPDURL )
            free( in->SCPDURL );

        if( in->controlURL )
            free( in->controlURL );

        if( in->eventURL )
            free( in->eventURL );

        if( in->UDN )
            ixmlFreeDOMString( in->UDN );

        if( in->subscriptionList )
            freeSubscriptionList( in->subscriptionList );

        in->TotalSubscriptions = 0;
        free( in );
    }
}
예제 #3
0
/************************************************************************
*	Function :	freeServiceList
*
*	Parameters :
*		service_info * head ;	Head of the service list to be freed
*
*	Description :	Free's memory allocated for the various components 
*		of each service entry in the service table.
*
*	Return : void ;
*
*	Note :
************************************************************************/
void
freeServiceList( service_info * head )
{
    service_info *next = NULL;

    while( head ) {
        if( head->serviceType )
            ixmlFreeDOMString( head->serviceType );
        if( head->serviceId )
            ixmlFreeDOMString( head->serviceId );
        if( head->SCPDURL )
            free( head->SCPDURL );
        if( head->controlURL )
            free( head->controlURL );
        if( head->eventURL )
            free( head->eventURL );
        if( head->UDN )
            ixmlFreeDOMString( head->UDN );
        if( head->subscriptionList )
            freeSubscriptionList( head->subscriptionList );

        head->TotalSubscriptions = 0;
        next = head->next;
        free( head );
        head = next;
    }
}
예제 #4
0
int
main (int argc, char* argv[])
{
	int i;

	if (argc < 2) {
		fprintf (stderr, "Usage: %s [xml files to load]\n",
			 argv[0]);
		exit (EXIT_FAILURE);
	}

	for (i = 1; i < argc; i++) {
		int rc;
		IXML_Document* doc = NULL;
		DOMString s;
		char* p;

		printf ("Test \"%s\" \n", argv[i]);
		printf ("    Loading ... ");
		fflush (stdout);

		rc = ixmlLoadDocumentEx (argv[i], &doc);
		if (rc != IXML_SUCCESS) {
			fprintf (stderr, 
				 "** error : can't load document %s : "
				 "error %d (%s)\n",
				 argv[i], rc, get_ixml_error_string (rc));
			exit (EXIT_FAILURE);
		}

		printf ("OK\n");

		printf ("    Printing ... ");
		fflush (stdout);
		
		s = ixmlPrintDocument (doc);
		if (s == NULL || s[0] == '\0') {
			fprintf (stderr, 
				 "** error : can't print loaded document %s\n",
				 argv[i]);
			exit (EXIT_FAILURE);
		}
		p = s + strlen(s)-1;
		while (isspace(*p) && p > s)
			p--;
		if (*s != '<' || *p != '>') {
			fprintf (stderr, 
				 "** error : malformed printed document '%s' :"
				 "%s\n", argv[i], s);
			exit (EXIT_FAILURE);
		}

		printf ("OK\n");

		ixmlFreeDOMString (s);
		ixmlDocument_free (doc);
	}
	
	exit (EXIT_SUCCESS);
}
예제 #5
0
/************************************************************************
*	Function :	removeServiceTable
*
*	Parameters :
*		IXML_Node *node ;	XML node information
*		service_table *in ;	service table from which services will be 
*							removed
*
*	Description :	This function assumes that services for a particular 
*		root device are placed linearly in the service table, and in the 
*		order in which they are found in the description document
*		all services for this root device are removed from the list
*
*	Return : int ;
*
*	Note :
************************************************************************/
int
removeServiceTable( IXML_Node * node,
                    service_table * in )
{
    IXML_Node *root = NULL;
    IXML_Node *currentUDN = NULL;
    DOMString UDN = NULL;
    IXML_NodeList *deviceList = NULL;
    service_info *current_service = NULL;
    service_info *start_search = NULL;
    service_info *prev_service = NULL;
    long unsigned int NumOfDevices = 0lu;
    long unsigned int i = 0lu;

    if( getSubElement( "root", node, &root ) ) {
        current_service = in->serviceList;
        start_search = in->serviceList;
        deviceList =
            ixmlElement_getElementsByTagName( ( IXML_Element * ) root,
                                              "device" );
        if( deviceList != NULL ) {
            NumOfDevices = ixmlNodeList_length( deviceList );
            for( i = 0lu; i < NumOfDevices; i++ ) {
                if( ( start_search )
                    && ( ( getSubElement( "UDN", node, &currentUDN ) )
                         && ( UDN = getElementValue( currentUDN ) ) ) ) {
                    current_service = start_search;
                    /*Services are put in the service table in the order in which they appear in the  */
                    /*description document, therefore we go through the list only once to remove a particular */
                    /*root device */
                    while( ( current_service )
                           && ( strcmp( current_service->UDN, UDN ) ) ) {
                        current_service = current_service->next;
			if( current_service != NULL) 
                        	prev_service = current_service->next;
                    }
                    while( ( current_service )
                           && ( !strcmp( current_service->UDN, UDN ) ) ) {
                        if( prev_service ) {
                            prev_service->next = current_service->next;
                        } else {
                            in->serviceList = current_service->next;
                        }
                        if( current_service == in->endServiceList )
                            in->endServiceList = prev_service;
                        start_search = current_service->next;
                        freeService( current_service );
                        current_service = start_search;
                    }
                    ixmlFreeDOMString( UDN );
                    UDN = NULL;
                }
            }

            ixmlNodeList_free( deviceList );
        }
    }
    return 1;
}
예제 #6
0
/************************************************************************
*	Function :	freeServiceTable
*
*	Parameters :
*		service_table * table ;	Service table whose memory needs to be 
*								freed
*
*	Description : Free's dynamic memory in table.
*		(does not free table, only memory within the structure)
*
*	Return : void ;
*
*	Note :
************************************************************************/
void
freeServiceTable( service_table * table )
{
    ixmlFreeDOMString( table->URLBase );
    freeServiceList( table->serviceList );
    table->serviceList = NULL;
    table->endServiceList = NULL;
}
예제 #7
0
파일: urlconfig.c 프로젝트: BlackGrey/upnp
/************************************************************************
*	Function :	configure_urlbase
*
*	Parameters :
*		INOUT IXML_Document *doc ;	IXML Description document
*		IN const struct sockaddr_in* serverAddr ;	socket address object
*					providing the IP address and port information
*		IN const char* alias ;	string containing the alias
*		IN time_t last_modified ;	time when the XML document was 
*					downloaded
*		OUT char docURL[LINE_SIZE] ;	buffer to hold the URL of the 
*					document.
*		INOUT IXML_Document *doc:dom document whose urlbase is to be modified
*		IN const struct sockaddr_in* serverAddr : ip address and port of 
*													the miniserver
*		IN const char* alias : a name to be used for the temp; e.g.:"foo.xml"
*		IN time_t last_modified :	time
*		OUT char docURL[LINE_SIZE] :	document URL
*
*	Description : Configure the full URL for the description document.
*		Create the URL document and add alias, description information.
*		The doc is added to the web server to be served using the given 
*		alias.
*
*	Return : int ;
*		UPNP_E_SUCCESS - On Success
*		UPNP_E_OUTOF_MEMORY - Default Error
*
*	Note :
************************************************************************/
int
configure_urlbase( INOUT IXML_Document * doc,
                   IN const struct sockaddr_in *serverAddr,
                   IN const char *alias,
                   IN time_t last_modified,
                   OUT char docURL[LINE_SIZE] )
{
    char *root_path = NULL;
    char *new_alias = NULL;
    char *xml_str = NULL;
    int err_code;
    char ipaddr_port[LINE_SIZE];

    err_code = UPNP_E_OUTOF_MEMORY; // default error

    // get IP address and port
    addrToString( serverAddr, ipaddr_port );

    // config url-base in 'doc'
    err_code = config_description_doc( doc, ipaddr_port, &root_path );
    if( err_code != UPNP_E_SUCCESS ) {
        goto error_handler;
    }
    // calc alias
    err_code = calc_alias( alias, root_path, &new_alias );
    if( err_code != UPNP_E_SUCCESS ) {
        goto error_handler;
    }
    // calc full url for desc doc
    err_code = calc_descURL( ipaddr_port, new_alias, docURL );
    if( err_code != UPNP_E_SUCCESS ) {
        goto error_handler;
    }
    // xml doc to str
    xml_str = ixmlPrintDocument( doc );
    if( xml_str == NULL ) {
        goto error_handler;
    }

    UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
        "desc url: %s\n", docURL );
    UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
        "doc = %s\n", xml_str );
    // store in web server
    err_code =
        web_server_set_alias( new_alias, xml_str, strlen( xml_str ),
                              last_modified );

error_handler:
    free( root_path );
    free( new_alias );

    if( err_code != UPNP_E_SUCCESS ) {
        ixmlFreeDOMString( xml_str );
    }
    return err_code;
}
예제 #8
0
/*!
 * \brief Frees memory used in notify_threads if the reference count is 0,
 * otherwise decrements the refrence count.
 */
static void free_notify_struct(
	/*! [in] Notify structure. */
	notify_thread_struct *input)
{
	(*input->reference_count)--;
	if (*input->reference_count == 0) {
		free(input->headers);
		ixmlFreeDOMString(input->propertySet);
		free(input->servId);
		free(input->UDN);
		free(input->reference_count);
	}
	free(input);
}
예제 #9
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;
}
예제 #10
0
파일: xml_util.c 프로젝트: f1vefour/djmount
/******************************************************************************
 * 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;
}
예제 #11
0
/*!
 * \brief Release memory allocated for the global web server root directory
 * and the global XML document. Resets the flag bWebServerState to
 * WEB_SERVER_DISABLED.
 *
 * \return Integer.
 */
static int get_file_info(
	/*! [in] Filename having the description document. */
	const char *filename,
	/*! [out] File information object having file attributes such as filelength,
	 * when was the file last modified, whether a file or a directory and
	 * whether the file or directory is readable. */
	struct File_Info *info)
{
	int code;
	struct osal_stat_t s;
	OSAL_FILE *fp;
	int rc = 0;
	struct tm date;
	char buffer[ASCTIME_R_BUFFER_SIZE];

	ixmlFreeDOMString(info->content_type);	
	info->content_type = NULL;
	code = osal_stat(filename, &s);
	if (code == -1)
		return -1;
	if (S_ISDIR(s.st_mode))
		info->is_directory = TRUE;
	else if (S_ISREG(s.st_mode))
		info->is_directory = FALSE;
	else
		return -1;
	if (info->is_directory == FALSE) {
		fp = osal_fopen(filename, "r");
		if (fp == NULL) return -1;
		osal_fclose(fp);
		/* check readable */
		info->is_readable = 1;
		info->file_length = s.st_size;
		info->last_modified = s.st_mtime;
		rc = get_content_type(filename, &info->content_type);
		UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
			"file info: %s, length: %lld, last_mod=%s readable=%d\n",
			filename, (long long)info->file_length,
			asctime_r(http_gmtime_r(&info->last_modified, &date), buffer),
			info->is_readable);
	}
	return rc;
}
예제 #12
0
static void FreeExtraHTTPHeaders(
	/*! [in] extra HTTP headers to free. */
	struct Extra_Headers *ExtraHeaders)
{
	struct Extra_Headers *extra_headers = ExtraHeaders;

	if (!ExtraHeaders) {
		return;
	}

	while (extra_headers->name) {
		free(extra_headers->name);
		if (extra_headers->value) free(extra_headers->value);
		if (extra_headers->resp) ixmlFreeDOMString(extra_headers->resp);
		extra_headers++;
	}

	free(ExtraHeaders);
}
예제 #13
0
파일: xml_util.c 프로젝트: f1vefour/djmount
/******************************************************************************
 * XMLUtil_GetDocumentString
 *****************************************************************************/
char*
XMLUtil_GetDocumentString (void* context, const IXML_Document* doc)
{
	// TBD XXX
	// TBD prepend <?xml version="1.0"?> if not already done ???
	// TBD XXX
	
	char* ret = NULL;
	if (doc) {
		DOMString s = ixmlPrintDocument (doc);
		if (s) {
			ret = talloc_strdup (context, s);
			ixmlFreeDOMString (s);
		} else {
			ret = talloc_strdup (context, "(error)");
		}
	} else {
		ret = talloc_strdup (context, "(null)");
	}
	return ret;
}
예제 #14
0
파일: rtpxml.c 프로젝트: layerfsd/cifssmb
void rtpxmlFreeDOMString(DOMString buf)
{
	ixmlFreeDOMString(buf);
}
예제 #15
0
/************************************************************************
*	Function :	getServiceList
*
*	Parameters :
*		IXML_Node *node ;	XML node information
*		service_info **end ; service added is returned to the output
*							parameter
*		char * URLBase ;	provides Base URL to resolve relative URL 
*
*	Description :	Returns pointer to service info after getting the 
*		sub-elements of the service info. 
*
*	Return : service_info * - pointer to the service info node ;
*
*	Note :
************************************************************************/
service_info *
getServiceList( IXML_Node * node,
                service_info ** end,
                char *URLBase )
{
    IXML_Node *serviceList = NULL;
    IXML_Node *current_service = NULL;
    IXML_Node *UDN = NULL;

    IXML_Node *serviceType = NULL;
    IXML_Node *serviceId = NULL;
    IXML_Node *SCPDURL = NULL;
    IXML_Node *controlURL = NULL;
    IXML_Node *eventURL = NULL;
    DOMString tempDOMString = NULL;
    service_info *head = NULL;
    service_info *current = NULL;
    service_info *previous = NULL;
    IXML_NodeList *serviceNodeList = NULL;
    int NumOfServices = 0;
    int i = 0;
    int fail = 0;

    if( getSubElement( "UDN", node, &UDN ) &&
        getSubElement( "serviceList", node, &serviceList ) ) {

        serviceNodeList = ixmlElement_getElementsByTagName( ( IXML_Element
                                                              * )
                                                            serviceList,
                                                            "service" );

        if( serviceNodeList != NULL ) {
            NumOfServices = ixmlNodeList_length( serviceNodeList );
            for( i = 0; i < NumOfServices; i++ ) {
                current_service = ixmlNodeList_item( serviceNodeList, i );
                fail = 0;

                if( current ) {
                    current->next =
                        ( service_info * )
                        malloc( sizeof( service_info ) );

                    previous = current;
                    current = current->next;
                } else {
                    head =
                        ( service_info * )
                        malloc( sizeof( service_info ) );
                    current = head;
                }

                if( !current ) {
                    freeServiceList( head );
                    return NULL;
                }

                current->next = NULL;
                current->controlURL = NULL;
                current->eventURL = NULL;
                current->serviceType = NULL;
                current->serviceId = NULL;
                current->SCPDURL = NULL;
                current->active = 1;
                current->subscriptionList = NULL;
                current->TotalSubscriptions = 0;

                if( !( current->UDN = getElementValue( UDN ) ) )
                    fail = 1;

                if( ( !getSubElement( "serviceType", current_service,
                                      &serviceType ) ) ||
                    ( !( current->serviceType =
                         getElementValue( serviceType ) ) ) )
                    fail = 1;

                if( ( !getSubElement( "serviceId", current_service,
                                      &serviceId ) ) ||
                    ( !
                      ( current->serviceId =
                        getElementValue( serviceId ) ) ) )
                    fail = 1;

                if( ( !
                      ( getSubElement
                        ( "SCPDURL", current_service, &SCPDURL ) ) )
                    || ( !( tempDOMString = getElementValue( SCPDURL ) ) )
                    ||
                    ( !
                      ( current->SCPDURL =
                        resolve_rel_url( URLBase, tempDOMString ) ) ) )
                    fail = 1;

                ixmlFreeDOMString( tempDOMString );
                tempDOMString = NULL;

                if( ( !
                      ( getSubElement
                        ( "controlURL", current_service, &controlURL ) ) )
                    ||
                    ( !( tempDOMString = getElementValue( controlURL ) ) )
                    ||
                    ( !
                      ( current->controlURL =
                        resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
                    UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                        "BAD OR MISSING CONTROL URL" );
                    UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                        "CONTROL URL SET TO NULL IN SERVICE INFO" );
                    current->controlURL = NULL;
                    fail = 0;
                }

                ixmlFreeDOMString( tempDOMString );
                tempDOMString = NULL;

                if( ( !
                      ( getSubElement
                        ( "eventSubURL", current_service, &eventURL ) ) )
                    || ( !( tempDOMString = getElementValue( eventURL ) ) )
                    ||
                    ( !
                      ( current->eventURL =
                        resolve_rel_url( URLBase, tempDOMString ) ) ) ) {
                    UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                        "BAD OR MISSING EVENT URL" );
                    UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                        "EVENT URL SET TO NULL IN SERVICE INFO" );
                    current->eventURL = NULL;
                    fail = 0;
                }

                ixmlFreeDOMString( tempDOMString );
                tempDOMString = NULL;

                if( fail ) {
                    freeServiceList( current );

                    if( previous )
                        previous->next = NULL;
                    else
                        head = NULL;

                    current = previous;
                }

            }

            ixmlNodeList_free( serviceNodeList );
        }

        ( *end ) = current;

        return head;
    } else
        return NULL;

}
예제 #16
0
/****************************************************************************
*	Function :	handle_query_variable
*
*	Parameters :
*		IN SOCKINFO *info :	Socket info
*		IN http_message_t* request : HTTP request
*		IN IXML_Document *xml_doc :	Document containing the variable request
*									SOAP message
*
*	Description :	This action handles the SOAP requests to querry the
*				state variables. This functionality has been deprecated in
*				the UPnP V1.0 architecture
*
*	Return :	void
*
*	Note :
****************************************************************************/
static UPNP_INLINE void
handle_query_variable( IN SOCKINFO * info,
                       IN http_message_t * request,
                       IN IXML_Document * xml_doc )
{
    Upnp_FunPtr soap_event_callback;
    void *cookie;
    char var_name[LINE_SIZE];
    struct Upnp_State_Var_Request variable;
    const char *err_str;
    int err_code;

    // get var name
    if( get_var_name( xml_doc, var_name ) != 0 ) {
        send_error_response( info, SOAP_INVALID_VAR,
                             Soap_Invalid_Var, request );
        return;
    }
    // get info for event
    if( get_device_info( request, 1, xml_doc, variable.DevUDN,
                         variable.ServiceID,
                         &soap_event_callback, &cookie ) != 0 ) {
        send_error_response( info, SOAP_INVALID_VAR,
                             Soap_Invalid_Var, request );
        return;
    }

    linecopy( variable.ErrStr, "" );
    variable.ErrCode = UPNP_E_SUCCESS;
    namecopy( variable.StateVarName, var_name );
    variable.CurrentVal = NULL;
    variable.CtrlPtIPAddr = info->foreign_ip_addr;

    // send event
    soap_event_callback( UPNP_CONTROL_GET_VAR_REQUEST, &variable, cookie );

    UpnpPrintf( UPNP_INFO, SOAP, __FILE__, __LINE__,
                "Return from callback for var request\n" );

    // validate, and handle result
    if( variable.CurrentVal == NULL ) {
        err_code = SOAP_ACTION_FAILED;
        err_str = Soap_Action_Failed;
        send_error_response( info, SOAP_INVALID_VAR,
                             Soap_Invalid_Var, request );
        return;
    }
    if( variable.ErrCode != UPNP_E_SUCCESS ) {
        if( strlen( variable.ErrStr ) > 0 ) {
            err_code = SOAP_INVALID_VAR;
            err_str = Soap_Invalid_Var;
        } else {
            err_code = variable.ErrCode;
            err_str = variable.ErrStr;
        }
        send_error_response( info, err_code, err_str, request );
        return;
    }
    // send response
    send_var_query_response( info, variable.CurrentVal, request );
    ixmlFreeDOMString( variable.CurrentVal );

}
예제 #17
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);
}
예제 #18
0
/* We take ownership of propertySet and will free it */
static int genaInitNotifyCommon(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	DOMString propertySet,
	const Upnp_SID sid)
{
	int ret = GENA_SUCCESS;
	int line = 0;

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

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

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN INITIAL NOTIFY COMMON");

	job = (ThreadPoolJob *)malloc(sizeof(ThreadPoolJob));
	if (job == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	memset(job, 0, sizeof(ThreadPoolJob));

	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: 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: SID %s", sid);
	sub->active = 1;

	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->ctime = time(0);
		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 {
			ListNode *node = ListAddTail(&sub->outgoing, job);
			if (node != NULL) {
				((ThreadPoolJob *)node->item)->jobId = STALE_JOBID;
				line = __LINE__;
				ret = GENA_SUCCESS;
			} else {
				line = __LINE__;
				ret = UPNP_E_OUTOF_MEMORY;
			}
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS) {
		free(job);
		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 COMMON, ret = %d",
		ret);

	return ret;
}
예제 #19
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;
}
예제 #20
0
int genaNotifyAll(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	char **VarNames,
	char **VarValues,
	int var_count)
{
	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");

	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;
	}

	ret = GeneratePropertySet(VarNames, VarValues, var_count, &propertySet);
	if (ret != XML_SUCCESS) {
		line = __LINE__;
		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, ret = %d",
		ret);

	return ret;
}
예제 #21
0
/*!
 * \brief Handles the SOAP requests to querry the state variables.
 * This functionality has been deprecated in the UPnP V1.0 architecture.
 */
static UPNP_INLINE void handle_query_variable(
    int iface,
	/*! [in] Socket info. */
	SOCKINFO *info,
	/*! [in] HTTP request. */
	http_message_t *request,
	/*! [in] Document containing the variable request SOAP message. */
	IXML_Document *xml_doc)
{
	Upnp_FunPtr soap_event_callback;
	void *cookie;
	char var_name[LINE_SIZE];
	struct Upnp_State_Var_Request variable;
	const char *err_str;
	int err_code;

	/* get var name */
	if (get_var_name(xml_doc, var_name) != 0) {
		send_error_response(info, SOAP_INVALID_VAR,
				    Soap_Invalid_Var, request);
		return;
	}
	/* get info for event */
	err_code = get_device_info(iface, request, 1, xml_doc,
				   info->foreign_sockaddr.ss_family,
				   variable.DevUDN,
				   variable.ServiceID,
				   &soap_event_callback, &cookie);
	if (err_code != 0) {
		send_error_response(info, SOAP_INVALID_VAR,
				    Soap_Invalid_Var, request);
		return;
	}
	linecopy(variable.ErrStr, "");
	variable.ErrCode = UPNP_E_SUCCESS;
	namecopy(variable.StateVarName, var_name);
	variable.CurrentVal = NULL;
	variable.CtrlPtIPAddr = info->foreign_sockaddr;
	/* send event */
	soap_event_callback(UPNP_CONTROL_GET_VAR_REQUEST, &variable, cookie);
	UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__,
		   "Return from callback for var request\n");
	/* validate, and handle result */
	if (variable.CurrentVal == NULL) {
		send_error_response(info, SOAP_INVALID_VAR, Soap_Invalid_Var,
				    request);
		return;
	}
	if (variable.ErrCode != UPNP_E_SUCCESS) {
		if (strlen(variable.ErrStr) > 0) {
			err_code = SOAP_INVALID_VAR;
			err_str = Soap_Invalid_Var;
		} else {
			err_code = variable.ErrCode;
			err_str = variable.ErrStr;
		}
		send_error_response(info, err_code, err_str, request);
		return;
	}
	/* send response */
	send_var_query_response(info, variable.CurrentVal, request);
	ixmlFreeDOMString(variable.CurrentVal);
}
예제 #22
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);
	}
}
예제 #23
0
/********************************************************************************
 * 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\n======================================================================\n" );
    SampleUtil_Print
        ( "----------------------------------------------------------------------\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     =  %d\n",
                                  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     =  %d\n",
                                  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 = ixmlPrintDocument( a_event->ActionRequest );
                    if( xmlbuff )
                        SampleUtil_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionResult );
                    if( xmlbuff )
                        SampleUtil_Print( "ActResult   =  %s\n", xmlbuff );
                    if( 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     =  %d\n",
                                  a_event->ErrCode );
                SampleUtil_Print( "CtrlUrl     =  %s\n",
                                  a_event->CtrlUrl );
                if( a_event->ActionRequest ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionRequest );
                    if( xmlbuff )
                        SampleUtil_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionResult );
                    if( xmlbuff )
                        SampleUtil_Print( "ActResult   =  %s\n", xmlbuff );
                    if( 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     =  %d\n",
                                  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     =  %d\n",
                                  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 = ixmlPrintDocument( 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     =  %d\n",
                                  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     =  %d\n",
                                  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     =  %d\n",
                                  es_event->ErrCode );
                SampleUtil_Print( "PublisherURL=  %s\n",
                                  es_event->PublisherUrl );
                SampleUtil_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

    }
    SampleUtil_Print
        ( "----------------------------------------------------------------------\n" );
    SampleUtil_Print
        ( "======================================================================\n\n\n\n" );

    ithread_mutex_unlock( &display_mutex );
    return ( 0 );
}
예제 #24
0
void upnp_igd_print_event(upnp_igd_context *igd_ctxt, upnp_igd_print_level level, Upnp_EventType EventType, void *Event) {
	ithread_mutex_lock(&igd_ctxt->print_mutex);

	upnp_igd_print(igd_ctxt, level, "======================================================================");
	upnp_igd_print_event_type(igd_ctxt, level, 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;

		upnp_igd_print(igd_ctxt, level, "ErrCode     =  %s(%d)",
			UpnpGetErrorMessage(d_event->ErrCode), d_event->ErrCode);
		upnp_igd_print(igd_ctxt, level, "Expires     =  %d",  d_event->Expires);
		upnp_igd_print(igd_ctxt, level, "DeviceId    =  %s",  d_event->DeviceId);
		upnp_igd_print(igd_ctxt, level, "DeviceType  =  %s",  d_event->DeviceType);
		upnp_igd_print(igd_ctxt, level, "ServiceType =  %s",  d_event->ServiceType);
		upnp_igd_print(igd_ctxt, level, "ServiceVer  =  %s",  d_event->ServiceVer);
		upnp_igd_print(igd_ctxt, level, "Location    =  %s",  d_event->Location);
		upnp_igd_print(igd_ctxt, level, "OS          =  %s",  d_event->Os);
		upnp_igd_print(igd_ctxt, level, "Ext         =  %s",  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;

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

		upnp_igd_print(igd_ctxt, level, "ErrCode     =  %s(%d)",
			UpnpGetErrorMessage(a_event->ErrCode), a_event->ErrCode);
		upnp_igd_print(igd_ctxt, level, "CtrlUrl     =  %s", a_event->CtrlUrl);
		if (a_event->ActionRequest) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->ActionRequest);
			if (xmlbuff) {
				upnp_igd_print(igd_ctxt, level, "ActRequest  =  %s", xmlbuff);
				ixmlFreeDOMString(xmlbuff);
			}
			xmlbuff = NULL;
		} else {
			upnp_igd_print(igd_ctxt, level, "ActRequest  =  (null)");
		}
		if (a_event->ActionResult) {
			xmlbuff = ixmlPrintNode((IXML_Node *)a_event->ActionResult);
			if (xmlbuff) {
				upnp_igd_print(igd_ctxt, level, "ActResult   =  %s", xmlbuff);
				ixmlFreeDOMString(xmlbuff);
			}
			xmlbuff = NULL;
		} else {
			upnp_igd_print(igd_ctxt, level, "ActResult   =  (null)");
		}
		break;
	}
	case UPNP_CONTROL_GET_VAR_REQUEST: {
		struct Upnp_State_Var_Request *sv_event =
			(struct Upnp_State_Var_Request *)Event;

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

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

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

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

		upnp_igd_print(igd_ctxt, level, "SID         =  %s", es_event->Sid);
		upnp_igd_print(igd_ctxt, level, "ErrCode     =  %s(%d)",
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		upnp_igd_print(igd_ctxt, level, "TimeOut     =  %d", 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;

		upnp_igd_print(igd_ctxt, level, "SID         =  %s", es_event->Sid);
		upnp_igd_print(igd_ctxt, level, "ErrCode     =  %s(%d)",
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		upnp_igd_print(igd_ctxt, level, "PublisherURL=  %s", es_event->PublisherUrl);
		upnp_igd_print(igd_ctxt, level, "TimeOut     =  %d", 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;

		upnp_igd_print(igd_ctxt, level, "SID         =  %s", es_event->Sid);
		upnp_igd_print(igd_ctxt, level, "ErrCode     =  %s(%d)",
			UpnpGetErrorMessage(es_event->ErrCode), es_event->ErrCode);
		upnp_igd_print(igd_ctxt, level, "PublisherURL=  %s", es_event->PublisherUrl);
		upnp_igd_print(igd_ctxt, level, "TimeOut     =  %d", es_event->TimeOut);
		break;
	}
	}
	upnp_igd_print(igd_ctxt, level,"======================================================================");

	ithread_mutex_unlock(&igd_ctxt->print_mutex);
}
예제 #25
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;
}
예제 #26
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 );
}
예제 #27
0
파일: webserver.c 프로젝트: MaTriXy/libupnp
/*!
 * \brief Processes the request and returns the result in the output parameters.
 *
 * \return
 * \li \c HTTP_BAD_REQUEST
 * \li \c HTTP_INTERNAL_SERVER_ERROR
 * \li \c HTTP_REQUEST_RANGE_NOT_SATISFIABLE
 * \li \c HTTP_FORBIDDEN
 * \li \c HTTP_NOT_FOUND
 * \li \c HTTP_NOT_ACCEPTABLE
 * \li \c HTTP_OK
 */
static int process_request(
	/*! [in] HTTP Request message. */
	http_message_t *req,
	/*! [out] Tpye of response. */
	enum resp_type *rtype,
	/*! [out] Headers. */
	membuffer *headers,
	/*! [out] Get filename from request document. */
	membuffer *filename,
	/*! [out] Xml alias document from the request document. */
	struct xml_alias_t *alias,
	/*! [out] Send Instruction object where the response is set up. */
	struct SendInstruction *RespInstr)
{
	int code;
	int err_code;

	char *request_doc;
	struct File_Info finfo;
	int using_alias;
	int using_virtual_dir;
	uri_type *url;
	const char *temp_str;
	int resp_major;
	int resp_minor;
	int alias_grabbed;
	size_t dummy;
	const char *extra_headers = NULL;

	print_http_headers(req);
	url = &req->uri;
	assert(req->method == HTTPMETHOD_GET ||
	       req->method == HTTPMETHOD_HEAD ||
	       req->method == HTTPMETHOD_POST ||
	       req->method == HTTPMETHOD_SIMPLEGET);
	/* init */
	memset(&finfo, 0, sizeof(finfo));
	request_doc = NULL;
	finfo.content_type = NULL;
	alias_grabbed = FALSE;
	err_code = HTTP_INTERNAL_SERVER_ERROR;	/* default error */
	using_virtual_dir = FALSE;
	using_alias = FALSE;

	http_CalcResponseVersion(req->major_version, req->minor_version,
				 &resp_major, &resp_minor);
	/* */
	/* remove dots */
	/* */
	request_doc = malloc(url->pathquery.size + 1);
	if (request_doc == NULL) {
		goto error_handler;	/* out of mem */
	}
	memcpy(request_doc, url->pathquery.buff, url->pathquery.size);
	request_doc[url->pathquery.size] = '\0';
	dummy = url->pathquery.size;
	remove_escaped_chars(request_doc, &dummy);
	code = remove_dots(request_doc, url->pathquery.size);
	if (code != 0) {
		err_code = HTTP_FORBIDDEN;
		goto error_handler;
	}
	if (*request_doc != '/') {
		/* no slash */
		err_code = HTTP_BAD_REQUEST;
		goto error_handler;
	}
	if (isFileInVirtualDir(request_doc)) {
		using_virtual_dir = TRUE;
		RespInstr->IsVirtualFile = 1;
		if (membuffer_assign_str(filename, request_doc) != 0) {
			goto error_handler;
		}
	} else {
		/* try using alias */
		if (is_valid_alias(&gAliasDoc)) {
			alias_grab(alias);
			alias_grabbed = TRUE;
			using_alias = get_alias(request_doc, alias, &finfo);
			if (using_alias == TRUE) {
				finfo.content_type =
				    ixmlCloneDOMString("text/xml");

				if (finfo.content_type == NULL) {
					goto error_handler;
				}
			}
		}
	}
	if (using_virtual_dir) {
		if (req->method != HTTPMETHOD_POST) {
			/* get file info */
			if (virtualDirCallback.
			    get_info(filename->buf, &finfo) != 0) {
				err_code = HTTP_NOT_FOUND;
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if ((virtualDirCallback.
				     get_info(filename->buf,
					      &finfo) != UPNP_E_SUCCESS)
				    || finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
			/* finally, get content type */
			/* if ( get_content_type(filename->buf, &content_type) != 0 ) */
			/*{ */
			/*  goto error_handler; */
			/* } */
		}
	} else if (!using_alias) {
		if (gDocumentRootDir.length == 0) {
			goto error_handler;
		}
		/* */
		/* get file name */
		/* */

		/* filename str */
		if (membuffer_assign_str(filename, gDocumentRootDir.buf) != 0 ||
		    membuffer_append_str(filename, request_doc) != 0) {
			goto error_handler;	/* out of mem */
		}
		/* remove trailing slashes */
		while (filename->length > 0 &&
		       filename->buf[filename->length - 1] == '/') {
			membuffer_delete(filename, filename->length - 1, 1);
		}
		if (req->method != HTTPMETHOD_POST) {
			/* get info on file */
			if (get_file_info(filename->buf, &finfo) != 0) {
				err_code = HTTP_NOT_FOUND;
				goto error_handler;
			}
			/* try index.html if req is a dir */
			if (finfo.is_directory) {
				if (filename->buf[filename->length - 1] == '/') {
					temp_str = "index.html";
				} else {
					temp_str = "/index.html";
				}
				if (membuffer_append_str(filename, temp_str) !=
				    0) {
					goto error_handler;
				}
				/* get info */
				if (get_file_info(filename->buf, &finfo) != 0 ||
				    finfo.is_directory) {
					err_code = HTTP_NOT_FOUND;
					goto error_handler;
				}
			}
			/* not readable */
			if (!finfo.is_readable) {
				err_code = HTTP_FORBIDDEN;
				goto error_handler;
			}
		}
		/* finally, get content type */
		/*      if ( get_content_type(filename->buf, &content_type) != 0 ) */
		/*      { */
		/*          goto error_handler; */
		/*      } */
	}
	RespInstr->ReadSendSize = finfo.file_length;
	/* Check other header field. */
	if ((code =
	     CheckOtherHTTPHeaders(req, RespInstr,
				   finfo.file_length)) != HTTP_OK) {
		err_code = code;
		goto error_handler;
	}
	if (req->method == HTTPMETHOD_POST) {
		*rtype = RESP_POST;
		err_code = HTTP_OK;
		goto error_handler;
	}
	/*extra_headers = UpnpFileInfo_get_ExtraHeaders(finfo); */
	if (!extra_headers) {
		extra_headers = "";
	}

	/* Check if chunked encoding should be used. */
	if (using_virtual_dir && finfo.file_length == UPNP_USING_CHUNKED) {
		/* Chunked encoding is only supported by HTTP 1.1 clients */
		if (resp_major == 1 && resp_minor == 1) {
			RespInstr->IsChunkActive = 1;
		} else {
			/* The virtual callback indicates that we should use
			 * chunked encoding however the client doesn't support
			 * it. Return with an internal server error. */
			err_code = HTTP_NOT_ACCEPTABLE;
			goto error_handler;
		}
	}

	if (RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "T" "GKLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (RespInstr->IsRangeActive && !RespInstr->IsChunkActive) {
		/* Content-Range: bytes 222-3333/4000  HTTP_PARTIAL_CONTENT */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "R" "N" "T" "GLD" "s" "tcS" "Xc" "sCc",
		    HTTP_PARTIAL_CONTENT,	/* status code */
		    RespInstr->ReadSendSize,	/* content length */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* range info */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else if (!RespInstr->IsRangeActive && RespInstr->IsChunkActive) {
		/* Transfer-Encoding: chunked */
		if (http_MakeMessage(headers, resp_major, resp_minor,
		    "RK" "TLD" "s" "tcS" "Xc" "sCc",
		    HTTP_OK,	/* status code */
		    finfo.content_type,	/* content type */
		    RespInstr,	/* language info */
		    "LAST-MODIFIED: ",
		    &finfo.last_modified,
		    X_USER_AGENT, extra_headers) != 0) {
			goto error_handler;
		}
	} else {
		/* !RespInstr->IsRangeActive && !RespInstr->IsChunkActive */
		if (RespInstr->ReadSendSize >= 0) {
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "N" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    RespInstr->ReadSendSize,	/* content length */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		} else {
			if (http_MakeMessage(headers, resp_major, resp_minor,
			    "R" "TLD" "s" "tcS" "Xc" "sCc",
			    HTTP_OK,	/* status code */
			    finfo.content_type,	/* content type */
			    RespInstr,	/* language info */
			    "LAST-MODIFIED: ",
			    &finfo.last_modified,
			    X_USER_AGENT,
			    extra_headers) != 0) {
				goto error_handler;
			}
		}
	}
	if (req->method == HTTPMETHOD_HEAD) {
		*rtype = RESP_HEADERS;
	} else if (using_alias) {
		/* GET xml */
		*rtype = RESP_XMLDOC;
	} else if (using_virtual_dir) {
		*rtype = RESP_WEBDOC;
	} else {
		/* GET filename */
		*rtype = RESP_FILEDOC;
	}
	/* simple get http 0.9 as specified in http 1.0 */
	/* don't send headers */
	if (req->method == HTTPMETHOD_SIMPLEGET) {
		membuffer_destroy(headers);
	}
	err_code = HTTP_OK;

 error_handler:
	free(request_doc);
	ixmlFreeDOMString(finfo.content_type);
	if (err_code != HTTP_OK && alias_grabbed) {
		alias_release(alias);
	}

	return err_code;
}
예제 #28
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;
}
예제 #29
0
/* We take ownership of propertySet and will free it */
static int genaNotifyAllCommon(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	DOMString propertySet)
{
	int ret = GENA_SUCCESS;
	int line = 0;

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

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

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

	/* Keep this allocation first */
	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;
	}

	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) {
				ThreadPoolJob *job = NULL;
				ListNode *node;

				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->ctime = time(0);
				thread_struct->device_handle = device_handle;

				maybeDiscardEvents(&finger->outgoing);
				job = (ThreadPoolJob *)malloc(sizeof(ThreadPoolJob));
				if (job == NULL) {
					line = __LINE__;
					ret = UPNP_E_OUTOF_MEMORY;
					break;
				}
				memset(job, 0, sizeof(ThreadPoolJob));
				TPJobInit(job, (start_routine)genaNotifyThread, thread_struct);
				TPJobSetFreeFunction(job, (free_routine)free_notify_struct);
				TPJobSetPriority(job, MED_PRIORITY);
				node = ListAddTail(&finger->outgoing, job);

				/* If there is only one element on the list (which we just
				   added), need to kickstart the threadpool */
				if (ListSize(&finger->outgoing) == 1) {
					ret = ThreadPoolAdd(&gSendThreadPool, job, NULL);
					if (ret != 0) {
						line = __LINE__;
						if (ret == EOUTOFMEM) {
							line = __LINE__;
							ret = UPNP_E_OUTOF_MEMORY;
						}
						break;
					}
					if (node) {
						((ThreadPoolJob *)(node->item))->jobId = STALE_JOBID;
					}
				}
				finger = GetNextSubscription(service, finger);
			}
		} else {
			line = __LINE__;
			ret = GENA_E_BAD_SERVICE;
		}
	}

ExitFunction:
	/* The only case where we want to free memory here is if the
	   struct was never queued. Else, let the normal cleanup take place.
	   reference_count is allocated first so it's ok to do nothing if it's 0
	*/
	if (reference_count && *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 COMMON, ret = %d",
		ret);

	return ret;
}
예제 #30
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;
}