Skip to content
This repository has been archived by the owner on Jun 27, 2019. It is now read-only.

Commit

Permalink
comms:http:client: Basic boolean node
Browse files Browse the repository at this point in the history
It's the counterpart of the http-server's boolean node.
  • Loading branch information
ceolin committed Sep 25, 2015
1 parent 94ce356 commit 8aaa733
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib/flow/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ source "src/modules/flow/udev/Kconfig"
source "src/modules/flow/unix-socket/Kconfig"
source "src/modules/flow/wallclock/Kconfig"
source "src/modules/flow/http-server/Kconfig"
source "src/modules/flow/http-client/Kconfig"
endmenu
6 changes: 6 additions & 0 deletions src/modules/flow/http-client/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
config FLOW_NODE_TYPE_HTTP_CLIENT
tristate "Node type: http_client"
depends on HTTP_CLIENT
default m
help
Provides an HTTP client node for basic packet types.
3 changes: 3 additions & 0 deletions src/modules/flow/http-client/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
obj-$(FLOW_NODE_TYPE_HTTP_CLIENT) += http-client.mod
obj-http-client-$(FLOW_NODE_TYPE_HTTP_CLIENT) := http-client.json http-client.o
obj-http-client-$(FLOW_NODE_TYPE_HTTP_CLIENT)-type := flow
261 changes: 261 additions & 0 deletions src/modules/flow/http-client/http-client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
/*
* This file is part of the Soletta Project
*
* Copyright (C) 2015 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sol-flow/http-client.h"
#include "sol-flow.h"
#include "sol-http.h"
#include "sol-http-client.h"
#include "sol-json.h"
#include "sol-mainloop.h"
#include "sol-util.h"
#include "sol-vector.h"
#include "sol_config.h"

struct http_data {
struct sol_ptr_vector pending_conns;
struct sol_str_slice key;
char *url;
};

static void
get_key(struct http_data *mdata)
{
char *ptr = NULL;

if (strstartswith(mdata->url, "http://"))
ptr = strstr(mdata->url + strlen("http://"), "/");
else if (strstartswith(mdata->url, "https://"))
ptr = strstr(mdata->url + strlen("https://"), "/");

if (ptr)
mdata->key = sol_str_slice_from_str(ptr);
else
mdata->key = (struct sol_str_slice){.len = 0, .data = NULL };
}

static void
boolean_request_finished(void *data,
const struct sol_http_client_connection *connection,
struct sol_http_response *response)
{
struct sol_flow_node *node = data;
struct http_data *mdata = sol_flow_node_get_private_data(node);
bool result = true;

if (sol_ptr_vector_remove(&mdata->pending_conns, connection) < 0)
SOL_WRN("Failed to find pending connection %p", connection);

if (!response) {
sol_flow_send_error_packet(node, EINVAL,
"Error while reaching %s", mdata->url);
return;
}
SOL_HTTP_RESPONSE_CHECK_API(response);

if (!response->content.used) {
sol_flow_send_error_packet(node, EINVAL,
"Empty response from %s", mdata->url);
return;
}

if (response->response_code != SOL_HTTP_STATUS_OK) {
sol_flow_send_error_packet(node, EINVAL,
"%s returned an unknown response code: %d",
mdata->url, response->response_code);
return;
}

if (streq(response->content_type, "application/json")) {
struct sol_json_scanner scanner;
struct sol_json_token token, key, value;
enum sol_json_loop_reason reason;

sol_json_scanner_init(&scanner, response->content.data, response->content.used);
SOL_JSON_SCANNER_OBJECT_LOOP (&scanner, &token, &key, &value, reason) {
if (!sol_json_token_str_eq(&token, mdata->key.data, mdata->key.len))
continue;
if (sol_json_token_get_type(&value) == SOL_JSON_TYPE_TRUE)
result = true;
else if (sol_json_token_get_type(&value) == SOL_JSON_TYPE_FALSE)
result = false;
else
goto err;
sol_flow_send_boolean_packet(node,
SOL_FLOW_NODE_TYPE_HTTP_CLIENT_BOOLEAN__OUT__OUT, result);
return;
}
} else {
if (!strncasecmp("true", response->content.data, response->content.used))
result = true;
else if (!strncasecmp("false", response->content.data, response->content.used))
result = false;
else
goto err;
sol_flow_send_boolean_packet(node,
SOL_FLOW_NODE_TYPE_HTTP_CLIENT_BOOLEAN__OUT__OUT, result);
return;
}

err:
sol_flow_send_error_packet(node, EINVAL,
"%s Could not parser the url's contents ", mdata->url);
}

static int
boolean_get_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
const struct sol_flow_packet *packet)
{
int r;
struct sol_http_param params;
struct http_data *mdata = data;
struct sol_http_client_connection *connection;

SOL_NULL_CHECK(mdata->url, -EINVAL);

sol_http_param_init(&params);
if (!sol_http_param_add(&params,
SOL_HTTP_REQUEST_PARAM_HEADER("Accept", "application/json"))) {
SOL_WRN("Failed to set query params");
sol_http_param_free(&params);
return -ENOMEM;
}

connection = sol_http_client_request(SOL_HTTP_METHOD_GET, mdata->url,
&params, boolean_request_finished, node);

sol_http_param_free(&params);

SOL_NULL_CHECK(connection, -ENOTCONN);

r = sol_ptr_vector_append(&mdata->pending_conns, connection);
if (r < 0) {
SOL_WRN("Failed to keep pending connection.");
sol_http_client_connection_cancel(connection);
return -ENOMEM;
}

return 0;
}

static int
boolean_post_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
const struct sol_flow_packet *packet)
{
int r;
bool b;
struct sol_http_param params;
struct http_data *mdata = data;
struct sol_http_client_connection *connection;

SOL_NULL_CHECK(mdata->url, -EINVAL);

r = sol_flow_packet_get_boolean(packet, &b);
SOL_INT_CHECK(r, < 0, r);

sol_http_param_init(&params);
if (!(sol_http_param_add(&params,
SOL_HTTP_REQUEST_PARAM_HEADER("Accept", "application/json"))) ||
!(sol_http_param_add(&params,
SOL_HTTP_REQUEST_PARAM_POST_FIELD("value", b ? "true" : "false")))) {
SOL_WRN("Failed to set query params");
sol_http_param_free(&params);
return -ENOMEM;
}
connection = sol_http_client_request(SOL_HTTP_METHOD_POST, mdata->url,
&params, boolean_request_finished, node);
sol_http_param_free(&params);

SOL_NULL_CHECK(connection, -ENOTCONN);

r = sol_ptr_vector_append(&mdata->pending_conns, connection);
if (r < 0) {
SOL_WRN("Failed to keep pending connection.");
sol_http_client_connection_cancel(connection);
return -ENOMEM;
}

return 0;
}

static int
boolean_url_process(struct sol_flow_node *node, void *data, uint16_t port, uint16_t conn_id,
const struct sol_flow_packet *packet)
{
int r;
const char *url;
struct http_data *mdata = data;

r = sol_flow_packet_get_string(packet, &url);
SOL_INT_CHECK(r, < 0, r);

mdata->url = strdup(url);
SOL_NULL_CHECK(mdata->url, -ENOMEM);
get_key(mdata);

return 0;
}

static void
boolean_close(struct sol_flow_node *node, void *data)
{
struct sol_http_client_connection *connection;
struct http_data *mdata = data;
uint16_t i;

free(mdata->url);
SOL_PTR_VECTOR_FOREACH_IDX (&mdata->pending_conns, connection, i)
sol_http_client_connection_cancel(connection);
sol_ptr_vector_clear(&mdata->pending_conns);
}

static int
boolean_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
struct http_data *mdata = data;
struct sol_flow_node_type_http_client_boolean_options *opts =
(struct sol_flow_node_type_http_client_boolean_options *)options;

mdata->url = strdup(opts->url);
SOL_NULL_CHECK(mdata->url, -EINVAL);
get_key(mdata);

sol_ptr_vector_init(&mdata->pending_conns);

return 0;
}

#include "http-client-gen.c"
65 changes: 65 additions & 0 deletions src/modules/flow/http-client/http-client.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"$schema": "http://solettaproject.github.io/soletta/schemas/node-type-genspec.schema",
"name": "http-client",
"meta": {
"author": "Intel Corporation",
"license": "BSD-3-Clause",
"version": "1"
},
"types": [
{
"name": "http-client/boolean",
"category": "output/network",
"description": "HTTP Client for boolean",
"methods": {
"close": "boolean_close",
"open": "boolean_open"
},
"options": {
"members": [
{
"data_type": "string",
"description": "The url that will be used on request and posts",
"name": "url"
}
],
"version": 1
},
"in_ports": [
{
"data_type": "string",
"description": "Replace the url set on options",
"methods": {
"process": "boolean_url_process"
},
"name": "URL"
},
{
"data_type": "any",
"description": "Get the contents of the specified url",
"methods": {
"process": "boolean_get_process"
},
"name": "GET"
},
{
"data_type": "boolean",
"description": "Post into the url",
"methods": {
"process": "boolean_post_process"
},
"name": "POST"
}
],
"out_ports": [
{
"data_type": "boolean",
"description": "The value received from the url",
"name": "OUT"
}
],
"private_data_type": "http_data",
"url": "http://solettaproject.org/doc/latest/node_types/http-client/boolean.html"
}
]
}

0 comments on commit 8aaa733

Please sign in to comment.