Пример #1
0
/*!
 * \brief Creates a HTTP request packet. Depending on the input parameter,
 * it either creates a service advertisement request or service shutdown
 * request etc.
 */
static void CreateServicePacket(
	/*! [in] type of the message (Search Reply, Advertisement
	 * or Shutdown). */
	int msg_type,
	/*! [in] ssdp type. */
	const char *nt,
	/*! [in] unique service name ( go in the HTTP Header). */
	char *usn,
	/*! [in] Location URL. */
	char *location,
	/*! [in] Service duration in sec. */
	int duration,
	/*! [out] Output buffer filled with HTTP statement. */
	char **packet,
	/*! [in] Address family of the HTTP request. */
	int AddressFamily,
	/*! [in] PowerState as defined by UPnP Low Power. */
	int PowerState,
	/*! [in] SleepPeriod as defined by UPnP Low Power. */
	int SleepPeriod,
	/*! [in] RegistrationState as defined by UPnP Low Power. */
	int RegistrationState)
{
	int ret_code;
	const char *nts;
	membuffer buf;

	/* Notf == 0 means service shutdown,
	 * Notf == 1 means service advertisement,
	 * Notf == 2 means reply */
	membuffer_init(&buf);
	buf.size_inc = (size_t)30;
	*packet = NULL;
	if (msg_type == MSGTYPE_REPLY) {
		if (PowerState > 0) {
#ifdef UPNP_HAVE_OPTSSDP
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "R" "sdc" "D" "sc" "ssc" "ssc" "ssc"
					    "S" "Xc" "ssc" "ssc"
					    "sdc" "sdc" "sdcc", HTTP_OK,
					    "CACHE-CONTROL: max-age=", duration,
					    "EXT:", "LOCATION: ", location,
					    "OPT: ",
					    "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
					    "01-NLS: ", gUpnpSdkNLSuuid,
					    X_USER_AGENT, "ST: ", nt, "USN: ",
					    usn, "Powerstate: ", PowerState,
					    "SleepPeriod: ", SleepPeriod,
					    "RegistrationState: ",
					    RegistrationState);
#else
                        ret_code = http_MakeMessage(&buf, 1, 1,
					    "R" "sdc" "D" "sc" "ssc"
					    "S" "ssc" "ssc"
					    "sdc" "sdc" "sdcc", HTTP_OK,
					    "CACHE-CONTROL: max-age=", duration,
					    "EXT:", "LOCATION: ", location,
					    "ST: ", nt, "USN: ",
					    usn, "Powerstate: ", PowerState,
					    "SleepPeriod: ", SleepPeriod,
					    "RegistrationState: ",
					    RegistrationState);
#endif /* UPNP_HAVE_OPTSSDP */
		} else {
#ifdef UPNP_HAVE_OPTSSDP
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "R" "sdc" "D" "sc" "ssc" "ssc" "ssc"
					    "S" "Xc" "ssc" "sscc", HTTP_OK,
					    "CACHE-CONTROL: max-age=", duration,
					    "EXT:", "LOCATION: ", location,
					    "OPT: ",
					    "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
					    "01-NLS: ", gUpnpSdkNLSuuid,
					    X_USER_AGENT, "ST: ", nt, "USN: ",
					    usn);
#else
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "R" "sdc" "D" "sc" "ssc"
					    "S" "ssc" "sscc", HTTP_OK,
					    "CACHE-CONTROL: max-age=", duration,
					    "EXT:", "LOCATION: ", location,
					    "ST: ", nt, "USN: ", usn);
#endif /* UPNP_HAVE_OPTSSDP */
		}
		if (ret_code != 0) {
			return;
		}
	} else if (msg_type == MSGTYPE_ADVERTISEMENT ||
		   msg_type == MSGTYPE_SHUTDOWN) {
		const char *host = NULL;

		if (msg_type == MSGTYPE_ADVERTISEMENT)
			nts = "ssdp:alive";
		else
			/* shutdown */
			nts = "ssdp:byebye";
		/* NOTE: The CACHE-CONTROL and LOCATION headers are not present in
		 * a shutdown msg, but are present here for MS WinMe interop. */
		switch (AddressFamily) {
		case AF_INET:
			host = SSDP_IP;
			break;
		default:
			if (isUrlV6UlaGua(location))
				host = "[" SSDP_IPV6_SITELOCAL "]";
			else
				host = "[" SSDP_IPV6_LINKLOCAL "]";
		}
		if (PowerState > 0) {
#ifdef UPNP_HAVE_OPTSSDP
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "Q" "sssdc" "sdc" "ssc" "ssc" "ssc"
					    "ssc" "ssc" "S" "Xc" "ssc"
					    "sdc" "sdc" "sdcc",
					    HTTPMETHOD_NOTIFY, "*", (size_t) 1,
					    "HOST: ", host, ":", SSDP_PORT,
					    "CACHE-CONTROL: max-age=", duration,
					    "LOCATION: ", location, "OPT: ",
					    "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
					    "01-NLS: ", gUpnpSdkNLSuuid, "NT: ",
					    nt, "NTS: ", nts, X_USER_AGENT,
					    "USN: ", usn, "Powerstate: ",
					    PowerState, "SleepPeriod: ",
					    SleepPeriod, "RegistrationState: ",
					    RegistrationState);
#else
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "Q" "sssdc" "sdc" "ssc"
					    "ssc" "ssc" "S" "ssc"
					    "sdc" "sdc" "sdcc",
					    HTTPMETHOD_NOTIFY, "*", (size_t) 1,
					    "HOST: ", host, ":", SSDP_PORT,
					    "CACHE-CONTROL: max-age=", duration,
					    "LOCATION: ", location, "NT: ", nt,
					    "NTS: ", nts,
					    "USN: ", usn, "Powerstate: ",
					    PowerState, "SleepPeriod: ",
					    SleepPeriod, "RegistrationState: ",
					    RegistrationState);
#endif /* UPNP_HAVE_OPTSSDP */
		} else {
#ifdef UPNP_HAVE_OPTSSDP 
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "Q" "sssdc" "sdc" "ssc" "ssc" "ssc"
					    "ssc" "ssc" "S" "Xc" "sscc",
					    HTTPMETHOD_NOTIFY, "*", (size_t) 1,
					    "HOST: ", host, ":", SSDP_PORT,
					    "CACHE-CONTROL: max-age=", duration,
					    "LOCATION: ", location, "OPT: ",
					    "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
					    "01-NLS: ", gUpnpSdkNLSuuid, "NT: ",
					    nt, "NTS: ", nts, X_USER_AGENT,
					    "USN: ", usn);
#else
			ret_code = http_MakeMessage(&buf, 1, 1,
					    "Q" "sssdc" "sdc" "ssc"
					    "ssc" "ssc" "S" "sscc",
					    HTTPMETHOD_NOTIFY, "*", (size_t) 1,
					    "HOST: ", host, ":", SSDP_PORT,
					    "CACHE-CONTROL: max-age=", duration,
					    "LOCATION: ", location, "NT: ", nt,
					    "NTS: ", nts, "USN: ", usn);
#endif /* UPNP_HAVE_OPTSSDP */
		}
		if (ret_code)
			return;
	} else
		/* unknown msg */
		assert(0);
	/* return msg */
	*packet = membuffer_detach(&buf);
	membuffer_destroy(&buf);

	return;
}
Пример #2
0
/************************************************************************
*	Function :	config_description_doc
*
*	Parameters :
*		INOUT IXML_Document *doc ;IMXL description document to be 
*					configured	
*		IN const char* ip_str ;	string containing the IP port number
*		OUT char** root_path_str ;	buffer to hold the root path
*					of the configured description document
*		INOUT IXML_Document *doc :	Description document
*		IN const char* ip_str :	ipaddress string
*		OUT char** root_path_str :	root path string
*
*	Description : Configure the description document. Add the standard 
*		format and then add information from the root device and any
*		child nodes.
*
*	Return : int ;
*		UPNP_E_SUCCESS - On Success
*		UPNP_E_OUTOF_MEMORY - Default Error
*		UPNP_E_INVALID_DESC - Invalid child node		
*		UPNP_E_INVALID_URL - Invalid node information
*
*	Note :
************************************************************************/
static int
config_description_doc( INOUT IXML_Document * doc,
                        IN const char *ip_str,
                        OUT char **root_path_str )
{
    xboolean addNew = FALSE;
    IXML_NodeList *baseList;
    IXML_Element *element = NULL;
    IXML_Element *newElement = NULL;
    IXML_Node *textNode = NULL;
    IXML_Node *rootNode = NULL;
    IXML_Node *urlbase_node = NULL;
    char *urlBaseStr = "URLBase";
    const DOMString domStr = NULL;
    uri_type uri;
    int err_code;
    int len;
    membuffer url_str;
    membuffer root_path;

    membuffer_init( &url_str );
    membuffer_init( &root_path );

    err_code = UPNP_E_OUTOF_MEMORY; // default error

    baseList = ixmlDocument_getElementsByTagName( doc, urlBaseStr );
    if( baseList == NULL ) {
        // urlbase not found -- create new one
        addNew = TRUE;
        element = ixmlDocument_createElement( doc, urlBaseStr );
        if( element == NULL ) {
            goto error_handler;
        }

        if( membuffer_append_str( &url_str, "http://" ) != 0 ||
            membuffer_append_str( &url_str, ip_str ) != 0 ||
            membuffer_append_str( &url_str, "/" ) != 0 ||
            membuffer_append_str( &root_path, "/" ) != 0 ) {
            goto error_handler;
        }

        rootNode = ixmlNode_getFirstChild( ( IXML_Node * ) doc );
        if( rootNode == NULL ) {
            err_code = UPNP_E_INVALID_DESC;
            goto error_handler;
        }

        err_code =
            ixmlNode_appendChild( rootNode, ( IXML_Node * ) element );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }

        textNode =
            ixmlDocument_createTextNode( doc, ( char * )url_str.buf );
        if( textNode == NULL ) {
            goto error_handler;
        }

        err_code =
            ixmlNode_appendChild( ( IXML_Node * ) element, textNode );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }

    } else {
        // urlbase found
        urlbase_node = ixmlNodeList_item( baseList, 0 );
        assert( urlbase_node != NULL );

        textNode = ixmlNode_getFirstChild( urlbase_node );
        if( textNode == NULL ) {
            err_code = UPNP_E_INVALID_DESC;
            goto error_handler;
        }

        domStr = ixmlNode_getNodeValue( textNode );
        if( domStr == NULL ) {
            err_code = UPNP_E_INVALID_URL;
            goto error_handler;
        }

        len = parse_uri( domStr, strlen( domStr ), &uri );
        if( len < 0 || uri.type != ABSOLUTE ) {
            err_code = UPNP_E_INVALID_URL;
            goto error_handler;
        }

        if( membuffer_assign( &url_str, uri.scheme.buff,
                              uri.scheme.size ) != 0 ||
            membuffer_append_str( &url_str, "://" ) != 0 ||
            membuffer_append_str( &url_str, ip_str ) != 0 ) {
            goto error_handler;
        }
        // add leading '/' if missing from relative path
        if( ( uri.pathquery.size > 0 && uri.pathquery.buff[0] != '/' ) ||
            ( uri.pathquery.size == 0 )
             ) {
            if( membuffer_append_str( &url_str, "/" ) != 0 ||
                membuffer_append_str( &root_path, "/" ) != 0 ) {
                goto error_handler;
            }
        }

        if( membuffer_append( &url_str, uri.pathquery.buff,
                              uri.pathquery.size ) != 0 ||
            membuffer_append( &root_path, uri.pathquery.buff,
                              uri.pathquery.size ) != 0 ) {
            goto error_handler;
        }
        // add trailing '/' if missing
        if( url_str.buf[url_str.length - 1] != '/' ) {
            if( membuffer_append( &url_str, "/", 1 ) != 0 ) {
                goto error_handler;
            }
        }

        err_code = ixmlNode_setNodeValue( textNode, url_str.buf );
        if( err_code != IXML_SUCCESS ) {
            goto error_handler;
        }
    }

    *root_path_str = membuffer_detach( &root_path );    // return path
    err_code = UPNP_E_SUCCESS;

  error_handler:
    if( err_code != UPNP_E_SUCCESS ) {
        ixmlElement_free( newElement );
    }

    ixmlNodeList_free( baseList );

    membuffer_destroy( &root_path );
    membuffer_destroy( &url_str );

    return err_code;
}