Exemple #1
0
/*!
 * \brief Initialize the global XML document. Allocate buffers for the XML
 * document.
 */
static UPNP_INLINE void glob_alias_init(void)
{
	struct xml_alias_t *alias = &gAliasDoc;

	membuffer_init(&alias->doc);
	membuffer_init(&alias->name);
	alias->ct = NULL;
	alias->last_modified = 0;
}
Exemple #2
0
/* Allocates curl_state data needed for a new Session object. */
VALUE session_alloc(VALUE klass) {
  struct curl_state* curl;
  VALUE obj = Data_Make_Struct(klass, struct curl_state, NULL, session_free, curl);

  membuffer_init( &curl->header_buffer );
  membuffer_init( &curl->body_buffer );
  cs_list_append(curl);

  return obj;
}
Exemple #3
0
ib_status_t ib_kvstore_riak_set_bucket_property_str(
    ib_kvstore_t *kvstore,
    const char *property,
    const char *value)
{
    assert(kvstore);
    assert(property);
    assert(value);
    const char *post_fmt = "{\"props\":{\"%s\":\"%s\"}}";
    membuffer_t request;
    ib_status_t rc;

    membuffer_init(kvstore, &request);
    request.read = 0;
    request.size =
        strlen(property) +    /* Property length. */
        strlen(value) +       /* Value length. */
        strlen(post_fmt) - 4; /* post_fmt - %s and %s. */

    /* Note: size+1 so we can use sprintf below. */
    request.buffer = kvmalloc(kvstore, request.size+1);
    if (!request.buffer) {
        return IB_EALLOC;
    }
    sprintf(request.buffer, post_fmt, property, value);

    rc = ib_kvstore_riak_set_bucket_property(kvstore, &request);

    cleanup_membuffer(&request);

    return rc;
}
Exemple #4
0
int web_server_init()
{
	int ret = 0;

	if (bWebServerState == WEB_SERVER_DISABLED) {
		/* decode media list */
		media_list_init();
		membuffer_init(&gDocumentRootDir);
		glob_alias_init();
		pVirtualDirList = NULL;

		/* Initialize callbacks */
		virtualDirCallback.get_info = NULL;
		virtualDirCallback.open = NULL;
		virtualDirCallback.read = NULL;
		virtualDirCallback.write = NULL;
		virtualDirCallback.seek = NULL;
		virtualDirCallback.close = NULL;

		if (ithread_mutex_init(&gWebMutex, NULL) == -1)
			ret = UPNP_E_OUTOF_MEMORY;
		else
			bWebServerState = WEB_SERVER_ENABLED;
	}

	return ret;
}
Exemple #5
0
void gena_process_unsubscribe_request(
	SOCKINFO *info,
	http_message_t *request)
{
    Upnp_SID sid;
    service_info *service;
    struct Handle_Info *handle_info;
    UpnpDevice_Handle device_handle;

    memptr temp_hdr;
    membuffer event_url_path;

    /* if a CALLBACK or NT header is present, then it is an error */
    if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
        httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
        error_respond( info, HTTP_BAD_REQUEST, request );
        return;
    }
    /* get SID */
    if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
        temp_hdr.length > SID_SIZE ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        return;
    }
    memcpy( sid, temp_hdr.buf, temp_hdr.length );
    sid[temp_hdr.length] = '\0';

    /* lookup service by eventURL */
    membuffer_init( &event_url_path );
    if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
                          request->uri.pathquery.size ) != 0 ) {
        error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
        return;
    }

    HandleLock();

    if( GetDeviceHandleInfoForPath(event_url_path.buf, info->foreign_sockaddr.ss_family,
								   &device_handle, &handle_info, &service) != HND_DEVICE ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        membuffer_destroy( &event_url_path );
        HandleUnlock();
        return;
    }
    membuffer_destroy( &event_url_path );

    /* validate service */
    if( service == NULL ||
        !service->active || GetSubscriptionSID( sid, service ) == NULL )
    {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        HandleUnlock();
        return;
    }

    RemoveSubscriptionSID(sid, service);
    error_respond(info, HTTP_OK, request);    /* success */

    HandleUnlock();
}
Exemple #6
0
int web_server_set_alias(const char *alias_name, 
	const char *alias_content, size_t alias_content_length,
	time_t last_modified)
{
	int ret_code;
	struct xml_alias_t alias;

	alias_release(&gAliasDoc);
	if (alias_name == NULL) {
		/* don't serve aliased doc anymore */
		return 0;
	}
	assert(alias_content != NULL);
	membuffer_init(&alias.doc);
	membuffer_init(&alias.name);
	alias.ct = NULL;
	do {
		/* insert leading /, if missing */
		if (*alias_name != '/')
			if (membuffer_assign_str(&alias.name, "/") != 0)
				break;	/* error; out of mem */
		ret_code = membuffer_append_str(&alias.name, alias_name);
		if (ret_code != 0)
			break;	/* error */
		if ((alias.ct = (int *)malloc(sizeof(int))) == NULL)
			break;	/* error */
		*alias.ct = 1;
		membuffer_attach(&alias.doc, (char *)alias_content,
				 alias_content_length);
		alias.last_modified = last_modified;
		/* save in module var */
		ithread_mutex_lock(&gWebMutex);
		gAliasDoc = alias;
		ithread_mutex_unlock(&gWebMutex);

		return 0;
	} while (FALSE);
	/* error handler */
	/* free temp alias */
	membuffer_destroy(&alias.name);
	membuffer_destroy(&alias.doc);
	free(alias.ct);

	return UPNP_E_OUTOF_MEMORY;
}
Exemple #7
0
void membuffer_destroy(membuffer *m)
{
	if (m == NULL) {
		return;
	}
	if(m->buf != NULL)
		tls_mem_free(m->buf);
	membuffer_init(m);
}
Exemple #8
0
/*!
 * \brief Returns OK message in the case of a subscription request.
 *
 * \return UPNP_E_SUCCESS if successful, otherwise the appropriate error code.
 */
static int respond_ok(
	/*! [in] Socket connection of request. */
	SOCKINFO *info,
	/*! [in] Accepted duration. */
	int time_out,
	/*! [in] Accepted subscription. */
	subscription *sub,
	/*! [in] Http request. */
	http_message_t *request)
{
    int major;
    int minor;
    membuffer response;
    int return_code;
    char timeout_str[100];
    int upnp_timeout = UPNP_TIMEOUT;
    int rc = 0;

    http_CalcResponseVersion( request->major_version,
                              request->minor_version, &major, &minor );

    if( time_out >= 0 ) {
        rc = snprintf( timeout_str, sizeof ( timeout_str ),
                       "TIMEOUT: Second-%d", time_out );
    } else {
        memset( timeout_str, 0, sizeof( timeout_str ) );
        strncpy( timeout_str, "TIMEOUT: Second-infinite",
                 sizeof ( timeout_str ) - 1);
    }
    if (rc < 0 || (unsigned int) rc >= sizeof ( timeout_str ) ) {
        error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); 
        return UPNP_E_OUTOF_MEMORY;
    }

    membuffer_init( &response );
    response.size_inc = 30;
    if( http_MakeMessage(
        &response, major, minor,
        "R" "D" "S" "N" "Xc" "ssc" "scc",
        HTTP_OK,
        (off_t)0,
        X_USER_AGENT,
        "SID: ", sub->sid,
        timeout_str ) != 0 ) {
        membuffer_destroy( &response );
        error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
        return UPNP_E_OUTOF_MEMORY;
    }

    return_code = http_SendMessage( info, &upnp_timeout, "b",
                                    response.buf, response.length );

    membuffer_destroy( &response );

    return return_code;
}
Exemple #9
0
/************************************************************************
*	Function :	membuffer_destroy
*
*	Parameters :
*		INOUT membuffer* m ;	buffer to be destroyed
*
*	Description : Free's memory allocated for membuffer* m.
*
*	Return : void ;
*
*	Note :
************************************************************************/
void
membuffer_destroy( INOUT membuffer * m )
{
    if( m == NULL ) {
        return;
    }

    free( m->buf );
    membuffer_init( m );
}
/*!
 * \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 #11
0
MemBuffer *
membuffer_new_from_buffer_dup (DWORD addr, Buffer *buf)
{
	MemBuffer *membuffer;

	if ((membuffer = malloc(sizeof(MemBuffer))) == NULL)
		return NULL;

	membuffer_init (membuffer, addr, buffer_dup(buf));

	return membuffer;
}
Exemple #12
0
/****************************************************************************
*	Function :	send_var_query_response
*
*	Parameters :
*			IN SOCKINFO *info :	socket info
*			IN const char* var_value :	value of the state variable
*			IN http_message_t* hmsg :	HTTP request
*
*	Description :	This function sends response of get var status
*
*	Return : void
*
*	Note :
****************************************************************************/
static UPNP_INLINE void
send_var_query_response( IN SOCKINFO * info,
                         IN const char *var_value,
                         IN http_message_t * hmsg )
{
    off_t content_length;
    int timeout_secs = SOAP_TIMEOUT;
    int major;
    int minor;
    const char *start_body =
        "<s:Envelope "
        "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
        "<s:Body>\n"
        "<u:QueryStateVariableResponse "
        "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<return>";

    const char *end_body =
        "</return>\n"
        "</u:QueryStateVariableResponse>\n"
        "</s:Body>\n" "</s:Envelope>\n";

    membuffer response;

    http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
                              &major, &minor );

    content_length = strlen( start_body ) + strlen( var_value ) +
                     strlen( end_body );

    // make headers
    membuffer_init( &response );

    if (http_MakeMessage(
                &response, major, minor,
                "RNsDsSXcc" "sss",
                HTTP_OK,
                content_length,
                ContentTypeHeader,
                "EXT:\r\n",
                X_USER_AGENT,
                start_body, var_value, end_body ) != 0 ) {
        membuffer_destroy( &response );
        return;                 // out of mem
    }

    // send msg
    http_SendMessage( info, &timeout_secs, "b",
                      response.buf, response.length );

    membuffer_destroy( &response );
}
Exemple #13
0
MemBuffer *
membuffer_new (DWORD addr, unsigned char *code, int size)
{
	MemBuffer *membuffer;

	if ((membuffer = malloc(sizeof(MemBuffer))) == NULL)
		return NULL;

	membuffer_init (membuffer, addr,
		buffer_new_from_ptr(code, size)
	);

	return membuffer;
}
Exemple #14
0
/*!
 * \brief Function to Notify a particular subscription of a particular event.
 *
 * In general the service should NOT be blocked around this call (this may
 * cause deadlock with a client).
 *
 * NOTIFY http request is sent and the reply is processed.
 *
 * \return GENA_SUCCESS if the event was delivered, otherwise returns the
 * 	appropriate error code.
 */
static int genaNotify(
	/*! [in] Null terminated, includes all headers (including \\r\\n) except SID and SEQ. */
	char *headers,
	/*! [in] The evented XML. */
	char *propertySet,
	/*! [in] subscription to be Notified, assumes this is valid for life of function. */
	subscription *sub)
{
	size_t i;
	membuffer mid_msg;
	uri_type *url;
	http_parser_t response;
	int return_code = -1;

	membuffer_init(&mid_msg);
	if (http_MakeMessage(&mid_msg, 1, 1,
			     "s" "ssc" "sdcc",
			     headers,
			     "SID: ", sub->sid,
			     "SEQ: ", sub->ToSendEventKey) != 0) {
		membuffer_destroy(&mid_msg);
		return UPNP_E_OUTOF_MEMORY;
	}
	/* send a notify to each url until one goes thru */
	for (i = 0; i < sub->DeliveryURLs.size; i++) {
		url = &sub->DeliveryURLs.parsedURLs[i];
		return_code = notify_send_and_recv(
			url, &mid_msg, propertySet, &response);
		if (return_code == UPNP_E_SUCCESS)
			break;
	}
	membuffer_destroy(&mid_msg);
	if (return_code == UPNP_E_SUCCESS) {
		if (response.msg.status_code == HTTP_OK)
			return_code = GENA_SUCCESS;
		else {
			if (response.msg.status_code == HTTP_PRECONDITION_FAILED)
				/*Invalid SID gets removed */
				return_code = GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB;
			else
				return_code = GENA_E_NOTIFY_UNACCEPTED;
		}
		httpmsg_destroy(&response.msg);
	}

	return return_code;
}
Exemple #15
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 #16
0
ib_status_t ib_kvstore_riak_set_bucket_property_int(
    ib_kvstore_t *kvstore,
    const char *property,
    int value)
{
    assert(kvstore);
    assert(property);
    const char *post_fmt = "{\"props\":{\"%s\":%d}}";
    membuffer_t request;
    const int digits = 6;
    size_t size;
    ib_status_t rc;

    if (value < 0) {
        return IB_EINVAL;
    }

    /* Digits is greater than 6, so we can't represent it in our buffer. */
    if (value > 999999) {
        return IB_EINVAL;
    }

    membuffer_init(kvstore, &request);
    request.read = 0;
    size = strlen(property) + digits + strlen(post_fmt)-4;
    request.buffer = kvmalloc(kvstore, size+1);
    if (!request.buffer) {
        return IB_EALLOC;
    }

    request.size = sprintf(request.buffer, post_fmt, property, value);

    rc = ib_kvstore_riak_set_bucket_property(kvstore, &request);

    cleanup_membuffer(&request);

    return rc;
}
Exemple #17
0
/*!
 * \brief Sends SOAP error response.
 */
static void send_error_response(
	/*! [in] Socket info. */
	IN SOCKINFO *info,
	/*! [in] Error code. */
	IN int error_code,
	/*! [in] Error message. */
	IN const char *err_msg,
	/*! [in] HTTP request. */
	IN http_message_t *hmsg)
{
	off_t content_length;
	int timeout_secs = SOAP_TIMEOUT;
	int major;
	int minor;
	const char *start_body =
		"<?xml version=\"1.0\"?>\n"
		"<s:Envelope "
		"xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
		"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
		"<s:Body>\n"
		"<s:Fault>\n"
		"<faultcode>s:Client</faultcode>\n"
		"<faultstring>UPnPError</faultstring>\n"
		"<detail>\n"
		"<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
		"<errorCode>";
	const char *mid_body =
		"</errorCode>\n"
		"<errorDescription>";
	const char *end_body =
		"</errorDescription>\n"
		"</UPnPError>\n"
		"</detail>\n"
		"</s:Fault>\n"
		"</s:Body>\n"
		"</s:Envelope>\n";
	char err_code_str[30];
	membuffer headers;

	memset(err_code_str, 0, sizeof(err_code_str));
	snprintf(err_code_str, sizeof(err_code_str), "%d", error_code);
	/* calc body len */
	content_length = (off_t) (strlen(start_body) + strlen(err_code_str) +
				  strlen(mid_body) + strlen(err_msg) +
				  strlen(end_body));
	http_CalcResponseVersion(hmsg->major_version, hmsg->minor_version,
				 &major, &minor);
	/* make headers */
	membuffer_init(&headers);
	if (http_MakeMessage(&headers, major, minor,
			"RNsDsSXcc" "sssss",
			500,
			content_length,
			ContentTypeHeader,
			"EXT:\r\n",
			X_USER_AGENT,
			start_body, err_code_str, mid_body, err_msg,
			end_body) != 0) {
		membuffer_destroy(&headers);
		/* out of mem */
		return;
	}
	/* send err msg */
	http_SendMessage(info, &timeout_secs, "b",
		headers.buf, headers.length);
	membuffer_destroy(&headers);
}
Exemple #18
0
/*!
 * \brief Sends the notify message and returns a reply.
 *
 * \return on success returns UPNP_E_SUCCESS, otherwise returns a UPNP error.
 *
 * \note called by genaNotify
 */
static UPNP_INLINE int notify_send_and_recv(
	/*! [in] subscription callback URL (URL of the control point). */
	uri_type *destination_url,
	/*! [in] Common HTTP headers. */
	membuffer *mid_msg,
	/*! [in] The evented XML. */
	char *propertySet,
	/*! [out] The response from the control point. */
	http_parser_t *response)
{
	uri_type url;
	SOCKET conn_fd;
	membuffer start_msg;
	int ret_code;
	int err_code;
	int timeout;
	SOCKINFO info;
	const char *CRLF = "\r\n";

	/* connect */
	UpnpPrintf(UPNP_ALL, GENA, __FILE__, __LINE__,
		"gena notify to: %.*s\n",
		(int)destination_url->hostport.text.size,
		destination_url->hostport.text.buff);

	conn_fd = http_Connect(destination_url, &url);
	if (conn_fd < 0)
		/* return UPNP error */
		return UPNP_E_SOCKET_CONNECT;
	ret_code = sock_init(&info, conn_fd);
	if (ret_code) {
		sock_destroy(&info, SD_BOTH);
		return ret_code;
	}
	/* make start line and HOST header */
	membuffer_init(&start_msg);
	if (http_MakeMessage(
			&start_msg, 1, 1,
			"q" "s",
			HTTPMETHOD_NOTIFY, &url,
			mid_msg->buf) != 0) {
		membuffer_destroy(&start_msg);
		sock_destroy(&info, SD_BOTH);
		return UPNP_E_OUTOF_MEMORY;
	}
	timeout = GENA_NOTIFICATION_SENDING_TIMEOUT;
	/* send msg (note: end of notification will contain "\r\n" twice) */
	ret_code = http_SendMessage(&info, &timeout,
		"bbb",
		start_msg.buf, start_msg.length,
		propertySet, strlen(propertySet),
		CRLF, strlen(CRLF));
	if (ret_code) {
		membuffer_destroy(&start_msg);
		sock_destroy(&info, SD_BOTH);
		return ret_code;
	}
	timeout = GENA_NOTIFICATION_ANSWERING_TIMEOUT;
	ret_code = http_RecvMessage(&info, response,
		HTTPMETHOD_NOTIFY, &timeout, &err_code);
	if (ret_code) {
		membuffer_destroy(&start_msg);
		sock_destroy(&info, SD_BOTH);
		httpmsg_destroy(&response->msg);
		return ret_code;
	}
	/* should shutdown completely when closing socket */
	sock_destroy(&info, SD_BOTH);
	membuffer_destroy(&start_msg);

	return UPNP_E_SUCCESS;
}
Exemple #19
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);
	}
}
Exemple #20
0
void gena_process_subscription_renewal_request(
	SOCKINFO *info,
	http_message_t *request)
{
    Upnp_SID sid;
    subscription *sub;
    int time_out = 1801;
    service_info *service;
    struct Handle_Info *handle_info;
    UpnpDevice_Handle device_handle;
    memptr temp_hdr;
    membuffer event_url_path;
    memptr timeout_hdr;

    /* if a CALLBACK or NT header is present, then it is an error */
    if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL ||
        httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) {
        error_respond( info, HTTP_BAD_REQUEST, request );
        return;
    }
    /* get SID */
    if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL ||
        temp_hdr.length > SID_SIZE ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        return;
    }
    memcpy( sid, temp_hdr.buf, temp_hdr.length );
    sid[temp_hdr.length] = '\0';

    /* lookup service by eventURL */
    membuffer_init( &event_url_path );
    if( membuffer_append( &event_url_path, request->uri.pathquery.buff,
                          request->uri.pathquery.size ) != 0 ) {
        error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
        return;
    }

    HandleLock();

    if (GetDeviceHandleInfoForPath(event_url_path.buf, info->foreign_sockaddr.ss_family,
								   &device_handle, &handle_info, &service) != HND_DEVICE ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        membuffer_destroy( &event_url_path );
        HandleUnlock();
        return;
    }
    membuffer_destroy( &event_url_path );

    /* get subscription */
    if( service == NULL ||
        !service->active ||
        ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) {
        error_respond( info, HTTP_PRECONDITION_FAILED, request );
        HandleUnlock();
        return;
    }

    UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
        "Renew request: Number of subscriptions already: %d\n "
        "Max Subscriptions allowed:%d\n",
        service->TotalSubscriptions,
        handle_info->MaxSubscriptions );
    /* too many subscriptions */
    if( handle_info->MaxSubscriptions != -1 &&
            service->TotalSubscriptions > handle_info->MaxSubscriptions ) {
        error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
        RemoveSubscriptionSID( sub->sid, service );
        HandleUnlock();
        return;
    }
    /* set the timeout */
    if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) {
        if( matchstr( timeout_hdr.buf, timeout_hdr.length,
                      "%iSecond-%d%0", &time_out ) == PARSE_OK ) {

            /*nothing */

        } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) ==
                   0 ) {

            time_out = -1;      /* inifinite timeout */

        } else {
            time_out = DEFAULT_TIMEOUT; /* default is > 1800 seconds */

        }
    }

    /* replace infinite timeout with max timeout, if possible */
    if( handle_info->MaxSubscriptionTimeOut != -1 ) {
        if( time_out == -1 ||
            time_out > handle_info->MaxSubscriptionTimeOut ) {
            time_out = handle_info->MaxSubscriptionTimeOut;
        }
    }

    if( time_out == -1 ) {
        sub->expireTime = 0;
    } else {
        sub->expireTime = time( NULL ) + time_out;
    }

    if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) {
        RemoveSubscriptionSID( sub->sid, service );
    }

    HandleUnlock();
}
Exemple #21
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;
}
Exemple #22
0
static ib_status_t kvset(
    ib_kvstore_t *kvstore,
    ib_kvstore_merge_policy_fn_t merge_policy,
    const ib_kvstore_key_t *key,
    ib_kvstore_value_t *value,
    ib_kvstore_cbdata_t *cbdata)
{

    char *url;
    ib_status_t rc;
    CURLcode curl_rc;
    ib_kvstore_riak_server_t *riak;
    struct curl_slist *header_list = NULL;

    membuffer_t response;
    membuffer_t value_buffer;
    riak_headers_t riak_headers;

    /* Callback data for the value we are setting. */
    membuffer_init(kvstore, &value_buffer);
    value_buffer.size = value->value_length;
    value_buffer.buffer = value->value;

    /* Callback data for reading in the body. */
    membuffer_init(kvstore, &response);

    /* Callback data for storing the CURL headers. */
    riak_headers_init(kvstore, &riak_headers);

    riak = (ib_kvstore_riak_server_t *)kvstore->server;
    rc = IB_OK;
    url = build_key_url(kvstore, riak, key);

    /* Set url. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Use PUT action. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_UPLOAD, 1);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_READDATA, &value_buffer);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_INFILESIZE,
        value_buffer.size);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_READFUNCTION,
        membuffer_readfunction);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_WRITEFUNCTION,
        membuffer_writefunction);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, &response);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_HEADERFUNCTION,
        &riak_header_capture);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, &riak_headers);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    header_list = build_custom_headers(kvstore, riak, value);
    if (header_list) {
        curl_rc = curl_easy_setopt(
            riak->curl,
            CURLOPT_HTTPHEADER,
            header_list);
        if (curl_rc) {
            rc = IB_EOTHER;
            goto exit;
        }
    }

    /* Perform the transaction. */
    curl_rc = curl_easy_perform(riak->curl);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

exit:

    if (header_list) {
        curl_slist_free_all(header_list);
    }

    if (response.buffer) {
        kvfree(kvstore, response.buffer);
    }

    cleanup_riak_headers(&riak_headers);

    curl_easy_reset(riak->curl);
    kvfree(kvstore, url);
    return rc;
}
Exemple #23
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;
}
Exemple #24
0
/*!
 * \brief This function retrives the name of the SOAP action.
 *
 * \return 0 if successful else returns appropriate error.
 */
static UPNP_INLINE int get_request_type(
	/*! [in] HTTP request. */
	http_message_t *request,
	/*! [out] SOAP action name. */
	memptr *action_name)
{
	memptr value;
	memptr ns_value, dummy_quote;
	http_header_t *hdr;
	char save_char;
	char *s;
	membuffer soap_action_name;
	size_t n;

	/* find soapaction header */
	if (request->method == SOAPMETHOD_POST) {
		if (!httpmsg_find_hdr(request, HDR_SOAPACTION, &value))
			return SREQ_HDR_NOT_FOUND;
	} else {
		/* M-POST */
		/* get NS value from MAN header */
		hdr = httpmsg_find_hdr(request, HDR_MAN, &value);
		if (hdr == NULL)
			return SREQ_HDR_NOT_FOUND;
		if (matchstr(value.buf, value.length, "%q%i ; ns = %s",
			     &dummy_quote, &ns_value) != 0)
			return SREQ_BAD_HDR_FORMAT;
		/* create soapaction name header */
		membuffer_init(&soap_action_name);
		if (membuffer_assign(&soap_action_name,
			ns_value.buf, ns_value.length) == UPNP_E_OUTOF_MEMORY ||
		    membuffer_append_str(&soap_action_name,
			"-SOAPACTION") == UPNP_E_OUTOF_MEMORY) {
			membuffer_destroy(&soap_action_name);
			return UPNP_E_OUTOF_MEMORY;
		}
		hdr = httpmsg_find_hdr_str(request, soap_action_name.buf);
		membuffer_destroy(&soap_action_name);
		if (!hdr)
			return SREQ_HDR_NOT_FOUND;
		value.buf = hdr->value.buf;
		value.length = hdr->value.length;
	}
	/* determine type */
	save_char = value.buf[value.length];
	value.buf[value.length] = '\0';
	s = strchr(value.buf, '#');
	if (s == NULL) {
		value.buf[value.length] = save_char;
		return SREQ_BAD_HDR_FORMAT;
	}
	/* move to value */
	s++;
	n = value.length - (size_t)(s - value.buf);
	if (matchstr(s, n, "%s", action_name) != PARSE_OK) {
		value.buf[value.length] = save_char;
		return SREQ_BAD_HDR_FORMAT;
	}
	/* action name or variable ? */
	if (memptr_cmp(action_name, "QueryStateVariable") == 0) {
		/* query variable */
		action_name->buf = NULL;
		action_name->length = 0;
	}
	/* restore */
	value.buf[value.length] = save_char;

	return 0;
}
Exemple #25
0
/**
 * Internal helper function to do the work for
 * ib_kvstore_riak_set_bucket_property_int and
 * ib_kvstore_riak_set_bucket_property_str.
 */
static ib_status_t ib_kvstore_riak_set_bucket_property(
    ib_kvstore_t *kvstore,
    membuffer_t *request)
{
    assert(kvstore);
    assert(request);
    assert(request->buffer);

    /* Constants for this function, alone. */
    const char *props_path = "/props";

    ib_kvstore_riak_server_t *riak;

    CURLcode curl_rc;
    struct curl_slist *header_list = NULL;
    size_t url_length;
    char *url;
    membuffer_t response;
    riak_headers_t headers;
    ib_status_t rc = IB_OK;

    riak_headers_init(kvstore, &headers);

    membuffer_init(kvstore, &response);

    riak = (ib_kvstore_riak_server_t *)kvstore->server;

    url_length = riak->bucket_url_len + strlen(props_path);

    url = kvmalloc(kvstore, url_length + 1);
    if (!url) {
        rc = IB_EALLOC;
        goto exit;
    }

    snprintf(url, url_length+1, "%s%s", riak->bucket_url, props_path);

    /* Set url. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Use PUT action. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_UPLOAD, 1);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Set request data. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_READDATA, request);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Set request data size. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_INFILESIZE, request->size);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Define how to read the request. */
    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_READFUNCTION,
        membuffer_readfunction);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Define how to write the response. */
    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_WRITEFUNCTION,
        membuffer_writefunction);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Set the response buffer. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, &response);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* How are headers captures. */
    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_HEADERFUNCTION,
        &riak_header_capture);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Where are headers captures. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, &headers);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    header_list = curl_slist_append(header_list, "Content-Type: application/json");
    if (!header_list) {
        rc = IB_EOTHER;
        goto exit;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_HTTPHEADER, header_list);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }

    /* Perform the transaction. */
    curl_rc = curl_easy_perform(riak->curl);
    if (curl_rc) {
        rc = IB_EOTHER;
        goto exit;
    }


exit:

    if (header_list) {
        curl_slist_free_all(header_list);
    }

    cleanup_membuffer(&response);
    cleanup_riak_headers(&headers);

    curl_easy_reset(riak->curl);
    kvfree(kvstore, url);
    return rc;
}
Exemple #26
0
void web_server_callback(http_parser_t *parser, INOUT http_message_t *req,
	SOCKINFO *info)
{
	int ret;
	int timeout = 0;
	enum resp_type rtype = 0;
	membuffer headers;
	membuffer filename;
	struct xml_alias_t xmldoc;
	struct SendInstruction RespInstr;

	/*Initialize instruction header. */
	RespInstr.IsVirtualFile = 0;
	RespInstr.IsChunkActive = 0;
	RespInstr.IsRangeActive = 0;
	RespInstr.IsTrailers = 0;
	memset(RespInstr.AcceptLanguageHeader, 0,
	       sizeof(RespInstr.AcceptLanguageHeader));
	/* init */
	membuffer_init(&headers);
	membuffer_init(&filename);

	/*Process request should create the different kind of header depending on the */
	/*the type of request. */
	ret = process_request(req, &rtype, &headers, &filename, &xmldoc,
		&RespInstr);
	if (ret != HTTP_OK) {
		/* send error code */
		http_SendStatusResponse(info, ret, req->major_version,
			req->minor_version);
	} else {
		/* send response */
		switch (rtype) {
		case RESP_FILEDOC:
			http_SendMessage(info, &timeout, "Ibf",
					 &RespInstr,
					 headers.buf, headers.length,
					 filename.buf);
			break;
		case RESP_XMLDOC:
			http_SendMessage(info, &timeout, "Ibb",
				&RespInstr,
				headers.buf, headers.length,
				xmldoc.doc.buf, xmldoc.doc.length);
			alias_release(&xmldoc);
			break;
		case RESP_WEBDOC:
			/*http_SendVirtualDirDoc(info, &timeout, "Ibf",
				&RespInstr,
				headers.buf, headers.length,
				filename.buf);*/
			http_SendMessage(info, &timeout, "Ibf",
				&RespInstr,
				headers.buf, headers.length,
				filename.buf);
			break;
		case RESP_HEADERS:
			/* headers only */
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			break;
		case RESP_POST:
			/* headers only */
			ret = http_RecvPostMessage(parser, info, filename.buf,
				&RespInstr);
			/* Send response. */
			http_MakeMessage(&headers, 1, 1,
				"RTLSXcCc",
				ret, "text/html", &RespInstr, X_USER_AGENT);
			http_SendMessage(info, &timeout, "b",
				headers.buf, headers.length);
			break;
		default:
			UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
				"webserver: Invalid response type received.\n");
			assert(0);
		}
	}
	UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__,
		   "webserver: request processed...\n");
	membuffer_destroy(&headers);
	membuffer_destroy(&filename);
}
Exemple #27
0
/**
 * Does a simple get of a Riak object.
 *
 * This will call riak_headers_init and membuffer_init on
 * @a riak_headers and @a response.
 *
 */
static ib_status_t riak_get(
    ib_kvstore_t *kvstore,
    ib_kvstore_riak_server_t *riak,
    const char *url,
    membuffer_t *response,
    riak_headers_t *riak_headers)
{

    CURLcode curl_rc;

    struct curl_slist *header_list = NULL;

    /* Callback data for reading in the body. */
    membuffer_init(kvstore, response);

    /* Callback data for storing the CURL headers. */
    riak_headers_init(kvstore, riak_headers);

    /* Set url. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url);
    if (curl_rc) {
        return IB_EOTHER;
    }

    /* Use HTTP GET. */
    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_HTTPGET, 1);
    if (curl_rc) {
        return IB_EOTHER;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_WRITEFUNCTION,
        membuffer_writefunction);
    if (curl_rc) {
        return IB_EOTHER;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, response);
    if (curl_rc) {
        return IB_EOTHER;
    }

    curl_rc = curl_easy_setopt(
        riak->curl,
        CURLOPT_HEADERFUNCTION,
        &riak_header_capture);
    if (curl_rc) {
        return IB_EOTHER;
    }

    curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, riak_headers);
    if (curl_rc) {
        return IB_EOTHER;
    }

    header_list = build_custom_headers(kvstore, riak, NULL);
    if (header_list) {
        curl_rc = curl_easy_setopt(
            riak->curl,
            CURLOPT_HTTPHEADER,
            header_list);
        if (curl_rc) {
            return IB_EOTHER;
        }
    }

    /* Perform the transaction. */
    curl_rc = curl_easy_perform(riak->curl);

    if (riak_headers->etag) {
        ib_kvstore_riak_set_etag(kvstore, riak_headers->etag);
    }

    if (riak_headers->x_riak_vclock) {
        ib_kvstore_riak_set_vclock(kvstore, riak_headers->x_riak_vclock);
    }

    /* Free the header list before checking curl_rc. */
    if (header_list) {
        curl_slist_free_all(header_list);
    }

    if (curl_rc) {
        return IB_EOTHER;
    }

    return IB_OK;
}
/****************************************************************************
*	Function :	send_error_response
*
*	Parameters :
*			IN SOCKINFO *info :	socket info
*			IN int error_code :	error code
*			IN const char* err_msg :	error message
*			IN http_message_t* hmsg :	HTTP request
*
*	Description :	This function sends SOAP error response
*
*	Return : void
*
*	Note :
****************************************************************************/
static void
send_error_response( IN SOCKINFO * info,
                     IN int error_code,
                     IN const char *err_msg,
                     IN http_message_t * hmsg )
{
    int content_length;
    int timeout_secs = SOAP_TIMEOUT;
    int major,
      minor;
    const char *start_body =
        "<s:Envelope\n"
        "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
        "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
        "<s:Body>\n"
        "<s:Fault>\n"
        "<faultcode>s:Client</faultcode>\n"
        "<faultstring>UPnPError</faultstring>\n"
        "<detail>\n"
        "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n"
        "<errorCode>";

    const char *mid_body = "</errorCode>\n" "<errorDescription>";

    const char *end_body =
        "</errorDescription>\n"
        "</UPnPError>\n"
        "</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n";

    char err_code_str[30];

    membuffer headers;

    sprintf( err_code_str, "%d", error_code );

    // calc body len
    content_length = strlen( start_body ) + strlen( err_code_str ) +
        strlen( mid_body ) + strlen( err_msg ) + strlen( end_body );

    http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version,
                              &major, &minor );

    // make headers
    membuffer_init( &headers );
    if( http_MakeMessage( &headers, major, minor,
                          "RNsDsSc" "sssss",
                          500,
                          content_length,
                          ContentTypeHeader,
                          "EXT:\r\n",
                          start_body, err_code_str, mid_body, err_msg,
                          end_body ) != 0 ) {
        membuffer_destroy( &headers );
        return;                 // out of mem
    }
    // send err msg
    http_SendMessage( info, &timeout_secs, "b",
                      headers.buf, headers.length );

    membuffer_destroy( &headers );
}
/****************************************************************************
*	Function :	get_request_type
*
*	Parameters :
*			IN http_message_t* request :	HTTP request
*			OUT memptr* action_name :	SOAP action name
*
*	Description :	This function retrives the name of the SOAP action
*
*	Return : int
*		0 if successful else returns appropriate error.
*	Note :
****************************************************************************/
static XINLINE int
get_request_type( IN http_message_t * request,
                  OUT memptr * action_name )
{
    memptr value;
    memptr ns_value,
      dummy_quote;
    http_header_t *hdr;
    char save_char;
    char *s;
    membuffer soap_action_name;

    // find soapaction header
    //
    if( request->method == SOAPMETHOD_POST ) {
        if( httpmsg_find_hdr( request, HDR_SOAPACTION, &value )
            == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }
    } else                      // M-POST
    {
        // get NS value from MAN header
        hdr = httpmsg_find_hdr( request, HDR_MAN, &value );
        if( hdr == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }

        if( matchstr( value.buf, value.length, "%q%i ; ns = %s",
                      &dummy_quote, &ns_value ) != 0 ) {
            return SREQ_BAD_HDR_FORMAT;
        }
        // create soapaction name header
        membuffer_init( &soap_action_name );
        if( ( membuffer_assign( &soap_action_name,
                                ns_value.buf, ns_value.length )
              == UPNP_E_OUTOF_MEMORY ) ||
            ( membuffer_append_str( &soap_action_name,
                                    "-SOAPACTION" ) ==
              UPNP_E_OUTOF_MEMORY )
             ) {
            membuffer_destroy( &soap_action_name );
            return UPNP_E_OUTOF_MEMORY;
        }

        hdr = httpmsg_find_hdr_str( request, soap_action_name.buf );
        membuffer_destroy( &soap_action_name );
        if( hdr == NULL ) {
            return SREQ_HDR_NOT_FOUND;
        }

        value.buf = hdr->value.buf;
        value.length = hdr->value.length;
    }

    // determine type
    //
    save_char = value.buf[value.length];
    value.buf[value.length] = '\0';

    s = strchr( value.buf, '#' );
    if( s == NULL ) {
        value.buf[value.length] = save_char;
        return SREQ_BAD_HDR_FORMAT;
    }

    s++;                        // move to value

    if( matchstr( s, value.length - ( s - value.buf ), "%s",
                  action_name ) != PARSE_OK ) {
        value.buf[value.length] = save_char;
        return SREQ_BAD_HDR_FORMAT;
    }
    // action name or variable ?
    if( memptr_cmp( action_name, "QueryStateVariable" ) == 0 ) {
        // query variable
        action_name->buf = NULL;
        action_name->length = 0;
    }

    value.buf[value.length] = save_char;    // restore
    return 0;
}
Exemple #30
0
static ib_status_t kvget(
    ib_kvstore_t *kvstore,
    const ib_kvstore_key_t *key,
    ib_kvstore_value_t ***values,
    size_t *values_length,
    ib_kvstore_cbdata_t *cbdata)
{
    ib_status_t rc;
    ib_kvstore_riak_server_t *riak;
    char *url;
    membuffer_t response;
    riak_headers_t riak_headers;

    membuffer_init(kvstore, &response);
    riak_headers_init(kvstore, &riak_headers);
    riak = (ib_kvstore_riak_server_t *)kvstore->server;

    url = build_key_url(kvstore, riak, key);

    rc = riak_get(kvstore, riak, url, &response, &riak_headers);
    if (rc != IB_OK) {
        goto exit;
    }

    if (riak_headers.status == 200) {
        *values_length = 1;

        /* Build 1-element array. */
        *values = kvmalloc(kvstore, sizeof(**values));
        if (*values == NULL) {
            rc = IB_EALLOC;
            goto exit;
        }

        /* Allocate kvstore value. */
        (*values)[0] = kvmalloc(kvstore, sizeof(*((*values)[0])));
        if (*values[0] == NULL) {
            rc = IB_EALLOC;
            goto exit;
        }

        rc = http_to_kvstore_value(
            kvstore,
            riak,
            &response,
            &riak_headers,
            (*values)[0]);
        goto exit;
    }

    /* Multiple choices. */
    else if (riak_headers.status == 300) {
        /* Current line. */
        char *cur;

        *values_length = 0;

        /* Count the siblings returned in the buffer. */
        for (size_t i = 0;
             i + 1 < response.read && response.buffer[i] != '\0';
             ++i)
        {
            /* Every sibling etag is preceded by a '\n' */
            if (response.buffer[i] == '\n' && isalnum(response.buffer[i+1]))
            {
                ++(*values_length);
            }
        }

        /* Build a *values_length element array. */
        *values = kvmalloc(kvstore, sizeof(**values) * *values_length);
        if (*values == NULL) {
            rc = IB_EALLOC;
            goto exit;
        }

        /* For each sibling, fetch it to be merged. */
        /* Skip the first line which is always "Siblings:\n". */
        cur = index(response.buffer, '\n') + 1;
        for (size_t i = 0; i < *values_length; ++i) {

            /* URL containing ?vtag=<ETag> from response. */
            char *vtag_url;
            const char *vtag = "?vtag=";
            char *eol = index(cur, '\n');

            *eol = '\0';

            membuffer_t tmp_buf;
            riak_headers_t tmp_headers;

            /* Init and Re-init. */
            membuffer_init(kvstore, &tmp_buf);
            riak_headers_init(kvstore, &tmp_headers);

            vtag_url = kvmalloc(
                kvstore,
                strlen(url) + strlen(vtag) + strlen(cur) + 1);
            if (!vtag_url) {
                rc = IB_EALLOC;
                goto exit;
            }
            sprintf(vtag_url, "%s%s%s", url, vtag, cur);

            rc = riak_get(kvstore, riak, vtag_url, &tmp_buf, &tmp_headers);
            if (rc != IB_OK) {
                /* Nop - just skip this and decrement the results. */
                --(*values_length);
                cleanup_membuffer(&tmp_buf);
                kvfree(kvstore, vtag_url);
                continue;
            }

            (*values)[i] = kvmalloc(kvstore, sizeof(*(*values)[i]));
            if ((*values)[i] == NULL) {
                /* On failure, free allocated keys. */
                for(size_t j = 0; j < i; j++) {
                    ib_kvstore_free_value(kvstore, (*values)[i]);
                }
                kvfree(kvstore, vtag_url);
                rc = IB_EALLOC;
                goto exit;
            }

            /* Convert the retrieved buffer data into a kvstore value. */
            rc = http_to_kvstore_value(
                kvstore,
                riak,
                &tmp_buf,
                &tmp_headers,
                (*values)[i]);

            cleanup_membuffer(&tmp_buf);
            cleanup_riak_headers(&tmp_headers);
            kvfree(kvstore, vtag_url);
            cur = eol+1;
        }
    }
    else if (riak_headers.status == 404) {
        *values_length = 0;
        *values = NULL;
        goto exit;
        rc = IB_ENOENT;
    }

    /* Before cleanly existing, set the riak etag and vclock to that of
     * the representative request, not the individual etag ones. */
    if (riak_headers.etag) {
        ib_kvstore_riak_set_etag(kvstore, riak_headers.etag);
    }

    if (riak_headers.x_riak_vclock) {
        ib_kvstore_riak_set_vclock(kvstore, riak_headers.x_riak_vclock);
    }

exit:

    cleanup_membuffer(&response);
    cleanup_riak_headers(&riak_headers);

    curl_easy_reset(riak->curl);
    kvfree(kvstore, url);
    return rc;
}