/*!
 * \brief Sends the UNSUBCRIBE gena request and recieves the response from the
 * 	device and returns it as a parameter.
 *
 * \returns 0 if successful, otherwise returns the appropriate error code.
 */
static int gena_unsubscribe(
	/*! [in] Event URL of the service. */
	IN const UpnpString *url,
	/*! [in] The subcription ID. */
	IN const UpnpString *sid,
	/*! [out] The UNSUBCRIBE response from the device. */
	OUT http_parser_t *response )
{
	int return_code;
	uri_type dest_url;
	membuffer request;

	/* parse url */
	return_code = http_FixStrUrl(
		UpnpString_get_String(url),
		UpnpString_get_Length(url),
		&dest_url);
	if (return_code != 0) {
		return return_code;
	}

	/* make request msg */
	membuffer_init(&request);
	request.size_inc = 30;
	return_code = http_MakeMessage(
		&request, 1, 1,
		"q" "ssc" "Uc",
		HTTPMETHOD_UNSUBSCRIBE, &dest_url,
		"SID: ", UpnpString_get_String(sid));

	/* Not able to make the message so destroy the existing buffer */
	if (return_code != 0) {
		membuffer_destroy(&request);

		return return_code;
	}

	/* send request and get reply */
	return_code = http_RequestAndResponse(
		&dest_url, request.buf, request.length,
		HTTPMETHOD_UNSUBSCRIBE, HTTP_DEFAULT_TIMEOUT, response);
	membuffer_destroy(&request);
	if (return_code != 0) {
		httpmsg_destroy(&response->msg);
	}

	if (return_code == 0 && response->msg.status_code != HTTP_OK) {
		return_code = UPNP_E_UNSUBSCRIBE_UNACCEPTED;
		httpmsg_destroy(&response->msg);
	}

	return return_code;
}
Exemple #2
0
/****************************************************************************
*	Function :	soap_request_and_response
*
*	Parameters :
*		IN membuffer* request :	request that will be sent to the device
*		IN uri_type* destination_url :	destination address string
*		OUT http_parser_t *response :	response from the device
*
*	Description :	This function sends the control point's request to the 
*		device and receives a response from it.
*
*	Return : int
*
*	Note :
****************************************************************************/
static int
soap_request_and_response( IN membuffer * request,
                           IN uri_type * destination_url,
                           OUT http_parser_t * response )
{
    int ret_code;

    ret_code = http_RequestAndResponse( destination_url, request->buf,
                                        request->length,
                                        SOAPMETHOD_POST,
                                        UPNP_TIMEOUT, response );
    if( ret_code != 0 ) {
        httpmsg_destroy( &response->msg );
        return ret_code;
    }
    /* method-not-allowed error */
    if( response->msg.status_code == HTTP_METHOD_NOT_ALLOWED ) {
        ret_code = add_man_header( request );   /* change to M-POST msg */
        if( ret_code != 0 ) {
            return ret_code;
        }

        httpmsg_destroy( &response->msg );  /* about to reuse response */

        /* try again */
        ret_code = http_RequestAndResponse( destination_url, request->buf,
                                            request->length,
                                            HTTPMETHOD_MPOST,
                                            UPNP_TIMEOUT,
                                            response );
        if( ret_code != 0 ) {
            httpmsg_destroy( &response->msg );
        }

    }

    return ret_code;
}
Exemple #3
0
/************************************************************************
* Function : gena_unsubscribe									
*																	
* Parameters:														
*	IN char *url: Event URL of the service
*	IN char *sid: The subcription ID.
*	OUT http_parser_t* response: The UNSUBCRIBE response from the device
*
* Description:														
*	This function sends the UNSUBCRIBE gena request and recieves the 
*	response from the device and returns it as a parameter
*
* Returns: int
*	return 0 if successful else returns appropriate error
***************************************************************************/
static int
gena_unsubscribe( IN char *url,
                  IN char *sid,
                  OUT http_parser_t * response )
{
    int return_code;
    uri_type dest_url;
    membuffer request;

    // parse url
    return_code = http_FixStrUrl( url, strlen( url ), &dest_url );
    if( return_code != 0 ) {
        return return_code;
    }
    // make request msg
    membuffer_init( &request );
    request.size_inc = 30;
    return_code = http_MakeMessage( &request, 1, 1,
                                    "q" "ssc" "U" "c",
                                    HTTPMETHOD_UNSUBSCRIBE, &dest_url,
                                    "SID: ", sid );

    //Not able to make the message so destroy the existing buffer
    if( return_code != 0 ) {
        membuffer_destroy( &request );
        return return_code;
    }
    // send request and get reply
    return_code = http_RequestAndResponse( &dest_url, request.buf,
                                           request.length,
                                           HTTPMETHOD_UNSUBSCRIBE,
                                           HTTP_DEFAULT_TIMEOUT,
                                           response );

    membuffer_destroy( &request );

    if( return_code != 0 )
        httpmsg_destroy( &response->msg );

    if( return_code == 0 && response->msg.status_code != HTTP_OK ) {
        return_code = UPNP_E_UNSUBSCRIBE_UNACCEPTED;
        httpmsg_destroy( &response->msg );
    }

    return return_code;
}
Exemple #4
0
/************************************************************************
* Function : gena_subscribe									
*																	
* Parameters:														
*	IN char *url: url of service to subscribe
*	INOUT int* timeout:subscription time desired (in secs)
*	IN char* renewal_sid:for renewal, this contains a currently h
*						 held subscription SID. For first time 
*						 subscription, this must be NULL
*	OUT char** sid: SID returned by the subscription or renew msg
*
* Description:														
*	This function subscribes or renew subscription
*
* Returns: int
*	return 0 if successful else returns appropriate error
***************************************************************************/
static int
gena_subscribe( IN char *url,
                INOUT int *timeout,
                IN char *renewal_sid,
                OUT char **sid )
{
    int return_code;
    memptr sid_hdr,
      timeout_hdr;
    char timeout_str[25];
    membuffer request;
    uri_type dest_url;
    http_parser_t response;

    *sid = NULL;                // init

    // request timeout to string
    if( ( timeout == NULL ) ||
        ( ( *timeout > 0 )
          && ( *timeout < CP_MINIMUM_SUBSCRIPTION_TIME ) ) ) {
        sprintf( timeout_str, "%d", CP_MINIMUM_SUBSCRIPTION_TIME );
    } else if( *timeout >= 0 ) {
        sprintf( timeout_str, "%d", *timeout );
    } else {
        strcpy( timeout_str, "infinite" );
    }

    // parse url
    return_code = http_FixStrUrl( url, strlen( url ), &dest_url );
    if( return_code != 0 ) {
        return return_code;
    }
    // make request msg
    membuffer_init( &request );
    request.size_inc = 30;
    if( renewal_sid ) {
        // renew subscription
        return_code = http_MakeMessage( &request, 1, 1,
                                        "q" "ssc" "ssc" "c",
                                        HTTPMETHOD_SUBSCRIBE, &dest_url,
                                        "SID: ", renewal_sid,
                                        "TIMEOUT: Second-", timeout_str );
    } else {
        // subscribe
        return_code = http_MakeMessage( &request, 1, 1,
                                        "q" "sssdsscc",
                                        HTTPMETHOD_SUBSCRIBE, &dest_url,
                                        "CALLBACK: <http://", LOCAL_HOST,
                                        ":", LOCAL_PORT,
                                        "/>\r\n" "NT: upnp:event\r\n"
                                        "TIMEOUT: Second-", timeout_str );
    }
    if( return_code != 0 ) {
        return return_code;
    }
    // send request and get reply
    return_code = http_RequestAndResponse( &dest_url, request.buf,
                                           request.length,
                                           HTTPMETHOD_SUBSCRIBE,
                                           HTTP_DEFAULT_TIMEOUT,
                                           &response );

    membuffer_destroy( &request );

    if( return_code != 0 ) {
        httpmsg_destroy( &response.msg );
        return return_code;
    }
    if( response.msg.status_code != HTTP_OK ) {
        httpmsg_destroy( &response.msg );
        return UPNP_E_SUBSCRIBE_UNACCEPTED;
    }
    // get SID and TIMEOUT
    if( httpmsg_find_hdr( &response.msg, HDR_SID, &sid_hdr ) == NULL ||
        sid_hdr.length == 0 ||
        httpmsg_find_hdr( &response.msg,
                          HDR_TIMEOUT, &timeout_hdr ) == NULL ||
        timeout_hdr.length == 0 ) {
        httpmsg_destroy( &response.msg );
        return UPNP_E_BAD_RESPONSE;
    }
    // save timeout
    if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0",
                  timeout ) == PARSE_OK ) {
        // nothing  
    } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) {
        *timeout = -1;
    } else {
        httpmsg_destroy( &response.msg );
        return UPNP_E_BAD_RESPONSE;
    }

    // save SID
    *sid = str_alloc( sid_hdr.buf, sid_hdr.length );
    if( *sid == NULL ) {
        httpmsg_destroy( &response.msg );
        return UPNP_E_OUTOF_MEMORY;
    }

    httpmsg_destroy( &response.msg );
    return UPNP_E_SUCCESS;
}
/*!
 * \brief Subscribes or renew subscription.
 *
 * \return 0 if successful, otherwise returns the appropriate error code.
 */
static int gena_subscribe(
	/*! [in] URL of service to subscribe. */
	IN const UpnpString *url,
	/*! [in,out] Subscription time desired (in secs). */
	INOUT int *timeout,
	/*! [in] for renewal, this contains a currently held subscription SID.
	 * For first time subscription, this must be NULL. */
	IN const UpnpString *renewal_sid,
	/*! [out] SID returned by the subscription or renew msg. */
	OUT UpnpString *sid)
{
	int return_code;
	int parse_ret = 0;
	int local_timeout = CP_MINIMUM_SUBSCRIPTION_TIME;
	memptr sid_hdr;
	memptr timeout_hdr;
	char timeout_str[25];
	membuffer request;
	uri_type dest_url;
	http_parser_t response;
	int rc = 0;

	UpnpString_clear(sid);

	/* request timeout to string */
	if (timeout == NULL) {
		timeout = &local_timeout;
	}
	if (*timeout < 0) {
		memset(timeout_str, 0, sizeof(timeout_str));
		strncpy(timeout_str, "infinite", sizeof(timeout_str) - 1);
	} else if(*timeout < CP_MINIMUM_SUBSCRIPTION_TIME) {
		rc = snprintf(timeout_str, sizeof(timeout_str),
			"%d", CP_MINIMUM_SUBSCRIPTION_TIME);
	} else {
		rc = snprintf(timeout_str, sizeof(timeout_str), "%d", *timeout);
	}
	if (rc < 0 || (unsigned int) rc >= sizeof(timeout_str))
		return UPNP_E_OUTOF_MEMORY;

	/* parse url */
	return_code = http_FixStrUrl(
		UpnpString_get_String(url),
		UpnpString_get_Length(url),
		&dest_url);
	if (return_code != 0) {
		return return_code;
	}

	/* make request msg */
	membuffer_init(&request);
	request.size_inc = 30;
	if (renewal_sid) {
		/* renew subscription */
		return_code = http_MakeMessage(
			&request, 1, 1,
			"q" "ssc" "sscc",
			HTTPMETHOD_SUBSCRIBE, &dest_url,
			"SID: ", UpnpString_get_String(renewal_sid),
			"TIMEOUT: Second-", timeout_str );
	} else {
		/* subscribe */
		if (dest_url.hostport.IPaddress.ss_family == AF_INET6) {
			struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&dest_url.hostport.IPaddress;
			return_code = http_MakeMessage(
				&request, 1, 1,
				"q" "sssdsc" "sc" "sscc",
				HTTPMETHOD_SUBSCRIBE, &dest_url,
				"CALLBACK: <http://[",
				(IN6_IS_ADDR_LINKLOCAL(&DestAddr6->sin6_addr) || strlen(gIF_IPV6_ULA_GUA) == 0) ?
					gIF_IPV6 : gIF_IPV6_ULA_GUA,
				"]:", LOCAL_PORT_V6, "/>",
				"NT: upnp:event",
				"TIMEOUT: Second-", timeout_str);
		} else {
			return_code = http_MakeMessage(
				&request, 1, 1,
				"q" "sssdsc" "sc" "sscc",
				HTTPMETHOD_SUBSCRIBE, &dest_url,
				"CALLBACK: <http://", gIF_IPV4, ":", LOCAL_PORT_V4, "/>",
				"NT: upnp:event",
				"TIMEOUT: Second-", timeout_str);
		}
	}
	if (return_code != 0) {
		return return_code;
	}

	/* send request and get reply */
	return_code = http_RequestAndResponse(&dest_url, request.buf,
		request.length,
		HTTPMETHOD_SUBSCRIBE,
		HTTP_DEFAULT_TIMEOUT,
		&response);
	membuffer_destroy(&request);

	if (return_code != 0) {
		httpmsg_destroy(&response.msg);

		return return_code;
	}
	if (response.msg.status_code != HTTP_OK) {
		httpmsg_destroy(&response.msg);

		return UPNP_E_SUBSCRIBE_UNACCEPTED;
	}

	/* get SID and TIMEOUT */
	if (httpmsg_find_hdr(&response.msg, HDR_SID, &sid_hdr) == NULL ||
	    sid_hdr.length == 0 ||
	    httpmsg_find_hdr( &response.msg, HDR_TIMEOUT, &timeout_hdr ) == NULL ||
	    timeout_hdr.length == 0 ) {
		httpmsg_destroy( &response.msg );

		return UPNP_E_BAD_RESPONSE;
	}

	/* save timeout */
	parse_ret = matchstr(timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", timeout);
	if (parse_ret == PARSE_OK) {
		/* nothing to do */
	} else if (memptr_cmp_nocase(&timeout_hdr, "Second-infinite") == 0) {
		*timeout = -1;
	} else {
		httpmsg_destroy( &response.msg );

		return UPNP_E_BAD_RESPONSE;
	}

	/* save SID */
	UpnpString_set_StringN(sid, sid_hdr.buf, sid_hdr.length);
	if (UpnpString_get_String(sid) == NULL) {
		httpmsg_destroy(&response.msg);

		return UPNP_E_OUTOF_MEMORY;
	}
	httpmsg_destroy(&response.msg);

	return UPNP_E_SUCCESS;
}