FS-9952: Big commit, first registered jsonrpc echo call successful, lots of cleanup remaining

This commit is contained in:
Shane Bryldt 2017-03-07 18:45:52 +00:00 committed by Mike Jerris
parent fd49aebb1d
commit 8f569f715b
25 changed files with 778 additions and 2813 deletions

View File

@ -11,23 +11,20 @@ libunqlite_la_CFLAGS = -DUNQLITE_ENABLE_THREADS
libunqlite_la_LIBADD = -lpthread
lib_LTLIBRARIES = libblade.la
libblade_la_SOURCES = src/blade.c src/blade_stack.c src/bpcp.c src/blade_datastore.c
libblade_la_SOURCES += src/blade_rpcproto.c
libblade_la_SOURCES += src/blade_identity.c src/blade_module.c src/blade_connection.c src/blade_module_wss.c
libblade_la_SOURCES += src/blade_session.c src/blade_protocol.c
libblade_la_SOURCES = src/blade.c src/blade_stack.c
libblade_la_SOURCES += src/blade_datastore.c
libblade_la_SOURCES += src/blade_identity.c src/blade_module.c src/blade_connection.c
libblade_la_SOURCES += src/blade_session.c src/blade_protocol.c src/blade_space.c src/blade_method.c
libblade_la_SOURCES += src/blade_module_wss.c
libblade_la_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
libblade_la_LDFLAGS = -version-info 0:1:0 -lncurses -lpthread -lm -lconfig $(AM_LDFLAGS)
libblade_la_LIBADD = libunqlite.la
library_includedir = $(prefix)/include
library_include_HEADERS = src/include/blade.h src/include/blade_types.h src/include/blade_stack.h
library_include_HEADERS += src/include/bpcp.h src/include/blade_datastore.h src/include/blade_rpcproto.h
library_include_HEADERS += src/include/blade_identity.h src/include/blade_module.h src/include/blade_connection.h
library_include_HEADERS += src/include/blade_session.h src/include/blade_protocol.h
library_include_HEADERS += src/include/blade_datastore.h
library_include_HEADERS += src/include/blade_identity.h src/include/blade_module.h src/include/blade_connection.h
library_include_HEADERS += src/include/blade_session.h src/include/blade_protocol.h src/include/blade_space.h src/include/blade_method.h
library_include_HEADERS += src/include/unqlite.h test/tap.h
tests: libblade.la
$(MAKE) -C test tests

View File

@ -495,6 +495,7 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc)
blade_transport_state_callback_t callback = NULL;
blade_connection_state_hook_t hook = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
cJSON *json = NULL;
blade_session_t *bs = NULL;
ks_bool_t done = KS_FALSE;
ks_assert(bc);
@ -514,14 +515,18 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc)
blade_connection_disconnect(bc);
break;
}
if (!(done = (json == NULL))) {
blade_session_t *bs = blade_handle_sessions_get(bc->handle, bc->session);
ks_assert(bs);
if (!bs) {
bs = blade_handle_sessions_get(bc->handle, bc->session);
ks_assert(bs);
}
blade_session_receiving_push(bs, json);
cJSON_Delete(json);
json = NULL;
}
}
if (bs) blade_session_read_unlock(bs);
callback = blade_connection_state_callback_lookup(bc, BLADE_CONNECTION_STATE_READY);
if (callback) hook = callback(bc, BLADE_CONNECTION_STATE_CONDITION_POST);

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2017, Shane Bryldt
* 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 the original author; nor the names of any 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 "blade.h"
struct blade_method_s {
blade_handle_t *handle;
ks_pool_t *pool;
blade_space_t *space;
const char *name;
blade_request_callback_t callback;
// @todo more fun descriptive information about the call for remote registrations
};
KS_DECLARE(ks_status_t) blade_method_create(blade_method_t **bmP, blade_space_t *bs, const char *name, blade_request_callback_t callback)
{
blade_handle_t *bh = NULL;
blade_method_t *bm = NULL;
ks_pool_t *pool = NULL;
ks_assert(bmP);
ks_assert(bs);
ks_assert(name);
bh = blade_space_handle_get(bs);
ks_assert(bh);
pool = blade_handle_pool_get(bh);
ks_assert(pool);
bm = ks_pool_alloc(pool, sizeof(blade_method_t));
bm->handle = bh;
bm->pool = pool;
bm->space = bs;
bm->name = name; // @todo dup and keep copy? should mostly be literals
bm->callback = callback;
*bmP = bm;
ks_log(KS_LOG_DEBUG, "Method Created: %s.%s\n", blade_space_path_get(bs), name);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_method_destroy(blade_method_t **bmP)
{
blade_method_t *bm = NULL;
ks_assert(bmP);
ks_assert(*bmP);
bm = *bmP;
ks_log(KS_LOG_DEBUG, "Method Destroyed: %s.%s\n", blade_space_path_get(bm->space), bm->name);
ks_pool_free(bm->pool, bmP);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(const char *) blade_method_name_get(blade_method_t *bm)
{
ks_assert(bm);
return bm->name;
}
KS_DECLARE(blade_request_callback_t) blade_method_callback_get(blade_method_t *bm)
{
ks_assert(bm);
return bm->callback;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -111,8 +111,10 @@ blade_connection_state_hook_t blade_transport_wss_on_state_connect_inbound(blade
blade_connection_state_hook_t blade_transport_wss_on_state_connect_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_detach(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_ready(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_detach_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_detach_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
@ -120,6 +122,9 @@ ks_status_t blade_transport_wss_init_create(blade_transport_wss_init_t **bt_wssi
ks_status_t blade_transport_wss_init_destroy(blade_transport_wss_init_t **bt_wssiP);
ks_bool_t blade_test_echo_request_handler(blade_request_t *breq);
ks_bool_t blade_test_echo_response_handler(blade_response_t *bres);
static blade_module_callbacks_t g_module_wss_callbacks =
{
@ -144,10 +149,10 @@ static blade_transport_callbacks_t g_transport_wss_callbacks =
blade_transport_wss_on_state_connect_outbound,
blade_transport_wss_on_state_attach_inbound,
blade_transport_wss_on_state_attach_outbound,
blade_transport_wss_on_state_detach,
blade_transport_wss_on_state_detach,
blade_transport_wss_on_state_ready,
blade_transport_wss_on_state_ready,
blade_transport_wss_on_state_detach_inbound,
blade_transport_wss_on_state_detach_outbound,
blade_transport_wss_on_state_ready_inbound,
blade_transport_wss_on_state_ready_outbound,
};
@ -385,6 +390,8 @@ ks_status_t blade_module_wss_config(blade_module_wss_t *bm_wss, config_setting_t
KS_DECLARE(ks_status_t) blade_module_wss_on_startup(blade_module_t *bm, config_setting_t *config)
{
blade_module_wss_t *bm_wss = NULL;
blade_space_t *space = NULL;
blade_method_t *method = NULL;
ks_assert(bm);
ks_assert(config);
@ -419,6 +426,17 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_startup(blade_module_t *bm, config_s
blade_handle_transport_register(bm_wss->handle, bm, BLADE_MODULE_WSS_TRANSPORT_NAME, bm_wss->transport_callbacks);
blade_space_create(&space, bm_wss->handle, "blade.test");
ks_assert(space);
blade_method_create(&method, space, "echo", blade_test_echo_request_handler);
ks_assert(method);
blade_space_methods_add(space, method);
blade_handle_space_register(space);
ks_log(KS_LOG_DEBUG, "Started\n");
return KS_STATUS_SUCCESS;
@ -428,6 +446,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
{
blade_module_wss_t *bm_wss = NULL;
blade_connection_t *bc = NULL;
ks_bool_t stopped = KS_FALSE;
ks_assert(bm);
@ -440,6 +459,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
ks_thread_join(bm_wss->listeners_thread);
ks_pool_free(bm_wss->pool, &bm_wss->listeners_thread);
bm_wss->shutdown = KS_FALSE;
stopped = KS_TRUE;
}
for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
@ -461,7 +481,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
while (list_size(&bm_wss->connected) > 0) ks_sleep_ms(100);
}
ks_log(KS_LOG_DEBUG, "Stopped\n");
if (stopped) ks_log(KS_LOG_DEBUG, "Stopped\n");
return KS_STATUS_SUCCESS;
}
@ -751,7 +771,6 @@ ks_status_t blade_transport_wss_write(blade_transport_wss_t *bt_wss, cJSON *json
ks_status_t blade_transport_wss_on_send(blade_connection_t *bc, cJSON *json)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_transport_wss_t *bt_wss = NULL;
ks_assert(bc);
@ -759,11 +778,7 @@ ks_status_t blade_transport_wss_on_send(blade_connection_t *bc, cJSON *json)
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
ret = blade_transport_wss_write(bt_wss, json);
cJSON_Delete(json);
return ret;
return blade_transport_wss_write(bt_wss, json);
}
ks_status_t blade_transport_wss_read(blade_transport_wss_t *bt_wss, cJSON **json)
@ -814,6 +829,29 @@ ks_status_t blade_transport_wss_on_receive(blade_connection_t *bc, cJSON **json)
return blade_transport_wss_read(bt_wss, json);
}
ks_status_t blade_transport_wss_rpc_error_send(blade_connection_t *bc, const char *id, int32_t code, const char *message)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_transport_wss_t *bt_wss = NULL;
cJSON *json = NULL;
ks_assert(bc);
ks_assert(id);
ks_assert(message);
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
blade_rpc_error_create(blade_connection_pool_get(bc), &json, NULL, id, code, message);
if (blade_transport_wss_write(bt_wss, json) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_DEBUG, "Failed to write error message\n");
ret = KS_STATUS_FAIL;
}
cJSON_Delete(json);
return ret;
}
blade_connection_state_hook_t blade_transport_wss_on_state_disconnect(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
blade_transport_wss_t *bt_wss = NULL;
@ -924,10 +962,11 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
{
blade_connection_state_hook_t ret = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
blade_transport_wss_t *bt_wss = NULL;
ks_pool_t *pool = NULL;
cJSON *json_req = NULL;
cJSON *json_res = NULL;
cJSON *params = NULL;
cJSON *result = NULL;
cJSON *json_params = NULL;
cJSON *json_result = NULL;
//cJSON *error = NULL;
blade_session_t *bs = NULL;
blade_handle_t *bh = NULL;
@ -948,6 +987,8 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
pool = blade_connection_pool_get(bc);
// @todo very temporary, really need monotonic clock and get timeout delay and sleep delay from config
timeout = ks_time_now() + (5 * KS_USEC_PER_SEC);
while (blade_transport_wss_read(bt_wss, &json_req) == KS_STATUS_SUCCESS) {
@ -958,6 +999,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
if (!json_req) {
ks_log(KS_LOG_DEBUG, "Failed to receive message before timeout\n");
blade_transport_wss_rpc_error_send(bc, NULL, -32600, "Timeout while expecting request");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
@ -966,7 +1008,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
jsonrpc = cJSON_GetObjectCstr(json_req, "jsonrpc"); // @todo check for definitions of these keys and fixed values
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
ks_log(KS_LOG_DEBUG, "Received message is not the expected protocol\n");
// @todo send error response before disconnecting, code = -32600 (invalid request)
blade_transport_wss_rpc_error_send(bc, NULL, -32600, "Invalid request, missing 'jsonrpc' field");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
@ -974,7 +1016,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
id = cJSON_GetObjectCstr(json_req, "id"); // @todo switch to number if we are not using a uuid for message id
if (!id) {
ks_log(KS_LOG_DEBUG, "Received message is missing 'id'\n");
// @todo send error response before disconnecting, code = -32600 (invalid request)
blade_transport_wss_rpc_error_send(bc, NULL, -32600, "Invalid request, missing 'id' field");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
@ -982,14 +1024,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
method = cJSON_GetObjectCstr(json_req, "method");
if (!method || strcasecmp(method, "blade.session.attach")) {
ks_log(KS_LOG_DEBUG, "Received message is missing 'method' or is an unexpected method\n");
// @todo send error response before disconnecting, code = -32601 (method not found)
blade_transport_wss_rpc_error_send(bc, id, -32601, "Missing or unexpected 'method' field");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
params = cJSON_GetObjectItem(json_req, "params");
if (params) {
sid = cJSON_GetObjectCstr(params, "session-id");
json_params = cJSON_GetObjectItem(json_req, "params");
if (json_params) {
sid = cJSON_GetObjectCstr(json_params, "session-id");
if (sid) {
// @todo validate uuid format by parsing, not currently available in uuid functions, send -32602 (invalid params) if invalid
ks_log(KS_LOG_DEBUG, "Session (%s) requested\n", sid);
@ -1019,7 +1061,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
if (blade_session_startup(bs) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_DEBUG, "Session (%s) startup failed\n", blade_session_id_get(bs));
// @todo send error response before disconnecting, code = -32603 (internal error)
blade_transport_wss_rpc_error_send(bc, id, -32603, "Internal error, session could not be started");
blade_session_read_unlock(bs);
blade_session_destroy(&bs);
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
@ -1030,17 +1072,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
}
// @todo wrapper to generate request and response
json_res = cJSON_CreateObject();
cJSON_AddStringToObject(json_res, "jsonrpc", "2.0");
cJSON_AddStringToObject(json_res, "id", id);
blade_rpc_response_create(pool, &json_res, &json_result, id);
ks_assert(json_res);
result = cJSON_CreateObject();
cJSON_AddStringToObject(result, "session-id", blade_session_id_get(bs));
cJSON_AddItemToObject(json_res, "result", result);
cJSON_AddStringToObject(json_result, "session-id", blade_session_id_get(bs));
// @todo send response
if (blade_transport_wss_write(bt_wss, json_res) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_DEBUG, "Failed to write message\n");
ks_log(KS_LOG_DEBUG, "Failed to write response message\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
@ -1064,14 +1103,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
blade_transport_wss_init_t *bt_wss_init = NULL;
ks_pool_t *pool = NULL;
cJSON *json_req = NULL;
cJSON *json_params = NULL;
cJSON *json_res = NULL;
uuid_t msgid;
const char *mid = NULL;
ks_time_t timeout;
const char *jsonrpc = NULL;
const char *id = NULL;
cJSON *error = NULL;
cJSON *result = NULL;
cJSON *json_error = NULL;
cJSON *json_result = NULL;
const char *sid = NULL;
blade_session_t *bs = NULL;
@ -1087,25 +1126,15 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
pool = blade_connection_pool_get(bc);
// @todo wrapper to build a request and response/error
json_req = cJSON_CreateObject();
cJSON_AddStringToObject(json_req, "jsonrpc", "2.0");
cJSON_AddStringToObject(json_req, "method", "blade.session.attach");
blade_rpc_request_create(pool, &json_req, &json_params, &mid, "blade.session.attach");
ks_assert(json_req);
ks_uuid(&msgid);
mid = ks_uuid_str(pool, &msgid);
cJSON_AddStringToObject(json_req, "id", mid);
if (bt_wss_init->session_id) {
cJSON *params = cJSON_CreateObject();
cJSON_AddStringToObject(params, "session-id", bt_wss_init->session_id);
cJSON_AddItemToObject(json_req, "params", params);
}
if (bt_wss_init->session_id) cJSON_AddStringToObject(json_params, "session-id", bt_wss_init->session_id);
ks_log(KS_LOG_DEBUG, "Session (%s) requested\n", (bt_wss_init->session_id ? bt_wss_init->session_id : "none"));
if (blade_transport_wss_write(bt_wss, json_req) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_DEBUG, "Failed to write message\n");
ks_log(KS_LOG_DEBUG, "Failed to write request message\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
@ -1134,26 +1163,26 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
id = cJSON_GetObjectCstr(json_res, "id"); // @todo switch to number if we are not using a uuid for message id
if (!id || strcasecmp(mid, id)) {
ks_log(KS_LOG_DEBUG, "Received message is missing 'id'\n");
ks_log(KS_LOG_DEBUG, "Received message has missing or unexpected 'id'\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
error = cJSON_GetObjectItem(json_res, "error");
if (error) {
json_error = cJSON_GetObjectItem(json_res, "error");
if (json_error) {
ks_log(KS_LOG_DEBUG, "Error message ... add the details\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
result = cJSON_GetObjectItem(json_res, "result");
if (!result) {
json_result = cJSON_GetObjectItem(json_res, "result");
if (!json_result) {
ks_log(KS_LOG_DEBUG, "Received message is missing 'result'\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
goto done;
}
sid = cJSON_GetObjectCstr(result, "session-id");
sid = cJSON_GetObjectCstr(json_result, "session-id");
if (!sid) {
ks_log(KS_LOG_DEBUG, "Received message 'result' is missing 'session-id'\n");
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
@ -1192,13 +1221,12 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
blade_connection_session_set(bc, blade_session_id_get(bs));
done:
if (mid) ks_pool_free(pool, &mid);
if (json_req) cJSON_Delete(json_req);
if (json_res) cJSON_Delete(json_res);
return ret;
}
blade_connection_state_hook_t blade_transport_wss_on_state_detach(blade_connection_t *bc, blade_connection_state_condition_t condition)
blade_connection_state_hook_t blade_transport_wss_on_state_detach_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
@ -1207,7 +1235,16 @@ blade_connection_state_hook_t blade_transport_wss_on_state_detach(blade_connecti
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
}
blade_connection_state_hook_t blade_transport_wss_on_state_ready(blade_connection_t *bc, blade_connection_state_condition_t condition)
blade_connection_state_hook_t blade_transport_wss_on_state_detach_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
}
blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
@ -1217,6 +1254,60 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready(blade_connectio
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
}
blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
if (condition == BLADE_CONNECTION_STATE_CONDITION_PRE) {
blade_session_t *bs = NULL;
cJSON *req = NULL;
bs = blade_handle_sessions_get(blade_connection_handle_get(bc), blade_connection_session_get(bc));
ks_assert(bs);
blade_rpc_request_create(blade_connection_pool_get(bc), &req, NULL, NULL, "blade.test.echo");
blade_session_send(bs, req, blade_test_echo_response_handler);
blade_session_read_unlock(bs);
}
ks_sleep_ms(1000);
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
}
ks_bool_t blade_test_echo_request_handler(blade_request_t *breq)
{
blade_session_t *bs = NULL;
cJSON *res = NULL;
ks_assert(breq);
ks_log(KS_LOG_DEBUG, "Request Received!\n");
bs = blade_handle_sessions_get(breq->handle, breq->session_id);
ks_assert(bs);
blade_rpc_response_create(breq->pool, &res, NULL, breq->message_id);
blade_session_send(bs, res, NULL);
blade_session_read_unlock(bs);
return KS_FALSE;
}
ks_bool_t blade_test_echo_response_handler(blade_response_t *bres)
{
ks_assert(bres);
ks_log(KS_LOG_DEBUG, "Response Received!\n");
return KS_FALSE;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -33,7 +33,11 @@
#include "blade.h"
KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, blade_handle_t *bh, const char *session_id, cJSON *json)
KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP,
blade_handle_t *bh,
const char *session_id,
cJSON *json,
blade_response_callback_t callback)
{
blade_request_t *breq = NULL;
ks_pool_t *pool = NULL;
@ -50,8 +54,9 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, blade_hand
breq->handle = bh;
breq->pool = pool;
breq->session_id = ks_pstrdup(pool, session_id);
breq->message = json;
breq->message = cJSON_Duplicate(json, 1);
breq->message_id = cJSON_GetObjectCstr(json, "id");
breq->callback = callback;
*breqP = breq;
@ -95,7 +100,7 @@ KS_DECLARE(ks_status_t) blade_response_create(blade_response_t **bresP, blade_ha
bres->pool = pool;
bres->session_id = ks_pstrdup(pool, session_id);
bres->request = breq;
bres->message = json;
bres->message = cJSON_Duplicate(json, 1);
*bresP = bres;
@ -120,6 +125,88 @@ KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP)
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_rpc_request_create(ks_pool_t *pool, cJSON **json, cJSON **params, const char **id, const char *method)
{
cJSON *root = NULL;
cJSON *p = NULL;
uuid_t msgid;
const char *mid = NULL;
ks_assert(pool);
ks_assert(json);
ks_assert(method);
root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "jsonrpc", "2.0");
ks_uuid(&msgid);
mid = ks_uuid_str(pool, &msgid);
cJSON_AddStringToObject(root, "id", mid);
ks_pool_free(pool, &mid);
cJSON_AddStringToObject(root, "method", method);
p = cJSON_CreateObject();
cJSON_AddItemToObject(root, "params", p);
*json = root;
if (params) *params = p;
if (id) *id = cJSON_GetObjectCstr(root, "id");
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_rpc_response_create(ks_pool_t *pool, cJSON **json, cJSON **result, const char *id)
{
cJSON *root = NULL;
cJSON *r = NULL;
ks_assert(pool);
ks_assert(json);
ks_assert(id);
root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "jsonrpc", "2.0");
cJSON_AddStringToObject(root, "id", id);
r = cJSON_CreateObject();
cJSON_AddItemToObject(root, "result", r);
*json = root;
if (result) *result = r;
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_rpc_error_create(ks_pool_t *pool, cJSON **json, cJSON **error, const char *id, int32_t code, const char *message)
{
cJSON *root = NULL;
cJSON *e = NULL;
ks_assert(pool);
ks_assert(json);
ks_assert(id);
ks_assert(message);
root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "jsonrpc", "2.0");
cJSON_AddStringToObject(root, "id", id);
e = cJSON_CreateObject();
cJSON_AddNumberToObject(e, "code", code);
cJSON_AddStringToObject(e, "message", message);
cJSON_AddItemToObject(root, "error", e);
*json = root;
if (error) *error = e;
return KS_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:

File diff suppressed because it is too large Load Diff

View File

@ -430,6 +430,7 @@ ks_status_t blade_session_state_on_destroy(blade_session_t *bs)
ks_assert(bs);
ks_log(KS_LOG_DEBUG, "Session (%s) state destroy\n", bs->id);
blade_handle_sessions_remove(bs);
blade_session_destroy(&bs);
@ -483,21 +484,31 @@ ks_status_t blade_session_state_on_ready(blade_session_t *bs)
}
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json)
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json, blade_response_callback_t callback)
{
blade_request_t *request = NULL;
const char *method = NULL;
const char *id = NULL;
ks_assert(bs);
ks_assert(json);
method = cJSON_GetObjectCstr(json, "method");
id = cJSON_GetObjectCstr(json, "id");
if (method) {
blade_request_create(&request, bs->handle, bs->id, json);
// @note This is scenario 1
// 1) Sending a request (client: method caller or consumer)
ks_log(KS_LOG_DEBUG, "Session (%s) sending request (%s) for %s\n", bs->id, id, method);
blade_request_create(&request, bs->handle, bs->id, json, callback);
ks_assert(request);
// @todo set request TTL and figure out when requests are checked for expiration (separate thread in the handle?)
blade_handle_requests_add(request);
} else {
// @note This is scenario 3
// 3) Sending a response or error (server: method callee or provider)
ks_log(KS_LOG_DEBUG, "Session (%s) sending response (%s)\n", bs->id, id);
}
if (list_empty(&bs->connections)) {
@ -516,20 +527,18 @@ KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json)
ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_request_t *breq = NULL;
blade_response_t *bres = NULL;
const char *jsonrpc = NULL;
const char *id = NULL;
const char *method = NULL;
ks_bool_t disconnect = KS_FALSE;
ks_assert(bs);
ks_assert(json);
ks_log(KS_LOG_DEBUG, "Session (%s) processing\n", bs->id);
// @todo teardown the message, convert into a blade_request_t or blade_response_t
// @todo validate the jsonrpc fields
jsonrpc = cJSON_GetObjectCstr(json, "jsonrpc");
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
@ -549,13 +558,50 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
method = cJSON_GetObjectCstr(json, "method");
if (method) {
// @todo use method to find RPC callbacks
// @note This is scenario 2
// 2) Receiving a request (server: method callee or provider)
blade_space_t *tmp_space = NULL;
blade_method_t *tmp_method = NULL;
blade_request_callback_t callback = NULL;
char *space_name = ks_pstrdup(bs->pool, method);
char *method_name = strrchr(space_name, '.');
blade_request_create(&breq, bs->handle, bs->id, json);
ks_log(KS_LOG_DEBUG, "Session (%s) receiving request (%s) for %s\n", bs->id, id, method);
if (!method_name || method_name == space_name) {
ks_pool_free(bs->pool, (void **)&space_name);
// @todo send error response, code = -32601 (method not found)
// @todo hangup session entirely?
return KS_STATUS_FAIL;
}
*method_name = '\0';
method_name++; // @todo check if can be postfixed safely on previous assignment, can't recall
tmp_space = blade_handle_space_lookup(bs->handle, space_name);
if (tmp_space) tmp_method = blade_space_methods_get(tmp_space, method_name);
ks_pool_free(bs->pool, (void **)&space_name);
if (!tmp_method) {
// @todo send error response, code = -32601 (method not found)
// @todo hangup session entirely?
return KS_STATUS_FAIL;
}
callback = blade_method_callback_get(tmp_method);
ks_assert(callback);
blade_request_create(&breq, bs->handle, bs->id, json, NULL);
ks_assert(breq);
// @todo call request callback handler
disconnect = callback(breq);
blade_request_destroy(&breq);
} else {
// @note This is scenario 4
// 4) Receiving a response or error (client: method caller or consumer)
ks_log(KS_LOG_DEBUG, "Session (%s) receiving response (%s)\n", bs->id, id);
breq = blade_handle_requests_get(bs->handle, id);
if (!breq) {
// @todo hangup session entirely?
@ -563,18 +609,20 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
}
blade_handle_requests_remove(breq);
method = cJSON_GetObjectCstr(breq->message, "method");
ks_assert(method);
// @todo use method to find RPC callbacks
blade_response_create(&bres, bs->handle, bs->id, breq, json);
ks_assert(bres);
// @todo call response callback handler
disconnect = breq->callback(bres);
blade_response_destroy(&bres);
}
return ret;
if (disconnect) {
// @todo hangup session entirely?
return KS_STATUS_FAIL;
}
return KS_STATUS_SUCCESS;
}
/* For Emacs:

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2017, Shane Bryldt
* 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 the original author; nor the names of any 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 "blade.h"
struct blade_space_s {
blade_handle_t *handle;
ks_pool_t *pool;
const char *path;
ks_hash_t *methods;
};
KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, const char *path)
{
blade_space_t *bs = NULL;
ks_pool_t *pool = NULL;
ks_assert(bsP);
ks_assert(bh);
ks_assert(path);
pool = blade_handle_pool_get(bh);
bs = ks_pool_alloc(pool, sizeof(blade_space_t));
bs->handle = bh;
bs->pool = pool;
bs->path = path; // @todo dup and keep copy? should mostly be literals
ks_hash_create(&bs->methods, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bs->pool);
ks_assert(bs);
*bsP = bs;
ks_log(KS_LOG_DEBUG, "Space Created: %s\n", path);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP)
{
blade_space_t *bs = NULL;
ks_hash_iterator_t *it = NULL;
ks_assert(bsP);
ks_assert(*bsP);
bs = *bsP;
for (it = ks_hash_first(bs->methods, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
void *key = NULL;
blade_method_t *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
blade_method_destroy(&value);
}
ks_hash_destroy(&bs->methods);
ks_log(KS_LOG_DEBUG, "Space Destroyed: %s\n", bs->path);
ks_pool_free(bs->pool, bsP);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs)
{
ks_assert(bs);
return bs->handle;
}
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs)
{
ks_assert(bs);
return bs->path;
}
KS_DECLARE(ks_status_t) blade_space_methods_add(blade_space_t *bs, blade_method_t *bm)
{
ks_status_t ret = KS_STATUS_SUCCESS;
const char *name = NULL;
blade_method_t *bm_old = NULL;
ks_assert(bs);
ks_assert(bm);
name = blade_method_name_get(bm);
ks_assert(name);
ks_hash_write_lock(bs->methods);
bm_old = ks_hash_search(bs->methods, (void *)name, KS_UNLOCKED);
if (bm_old) ks_hash_remove(bs->methods, (void *)name);
ret = ks_hash_insert(bs->methods, (void *)name, (void *)bm);
ks_hash_write_unlock(bs->methods);
if (bm_old) blade_method_destroy(&bm_old);
return ret;
}
KS_DECLARE(ks_status_t) blade_space_methods_remove(blade_space_t *bs, blade_method_t *bm)
{
ks_status_t ret = KS_STATUS_SUCCESS;
const char *name = NULL;
ks_assert(bs);
ks_assert(bm);
name = blade_method_name_get(bm);
ks_assert(name);
ks_hash_write_lock(bs->methods);
ks_hash_remove(bs->methods, (void *)name);
ks_hash_write_unlock(bs->methods);
return ret;
}
KS_DECLARE(blade_method_t *) blade_space_methods_get(blade_space_t *bs, const char *name)
{
blade_method_t *bm = NULL;
ks_assert(bs);
ks_assert(name);
ks_hash_read_lock(bs->methods);
bm = ks_hash_search(bs->methods, (void *)name, KS_UNLOCKED);
ks_hash_read_unlock(bs->methods);
return bm;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -48,6 +48,7 @@ struct blade_handle_s {
config_setting_t *config_datastore;
ks_hash_t *transports; // registered transports exposed by modules, NOT active connections
ks_hash_t *spaces; // registered method spaces exposed by modules
//blade_identity_t *identity;
blade_datastore_t *datastore;
@ -69,6 +70,7 @@ struct blade_handle_transport_registration_s {
blade_transport_callbacks_t *callbacks;
};
KS_DECLARE(ks_status_t) blade_handle_transport_registration_create(blade_handle_transport_registration_t **bhtrP,
ks_pool_t *pool,
blade_module_t *module,
@ -133,6 +135,8 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo
ks_hash_create(&bh->transports, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->transports);
ks_hash_create(&bh->spaces, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->spaces);
ks_hash_create(&bh->connections, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->connections);
@ -144,6 +148,8 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo
*bhP = bh;
ks_log(KS_LOG_DEBUG, "Created\n");
return KS_STATUS_SUCCESS;
}
@ -168,10 +174,13 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP)
ks_hash_destroy(&bh->requests);
ks_hash_destroy(&bh->sessions);
ks_hash_destroy(&bh->connections);
ks_hash_destroy(&bh->spaces);
ks_hash_destroy(&bh->transports);
if (bh->tpool && (flags & BH_MYTPOOL)) ks_thread_pool_destroy(&bh->tpool);
ks_log(KS_LOG_DEBUG, "Destroyed\n");
ks_pool_free(bh->pool, &bh);
if (pool && (flags & BH_MYPOOL)) {
@ -249,13 +258,22 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh)
blade_session_t *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
ks_hash_remove(bh->requests, key);
//ks_hash_remove(bh->sessions, key);
blade_session_hangup(value);
}
while (ks_hash_count(bh->sessions) > 0) ks_sleep_ms(100);
// @todo call onshutdown and onunload callbacks for modules from DSOs, which will unregister transports and disconnect remaining unattached connections
// @todo call onshutdown and onunload callbacks for modules from DSOs, which will unregister transports and spaces, and will disconnect remaining
// unattached connections
for (it = ks_hash_first(bh->spaces, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
void *key = NULL;
blade_space_t *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
blade_handle_space_unregister(value);
}
// @todo unload DSOs
@ -316,11 +334,81 @@ KS_DECLARE(ks_status_t) blade_handle_transport_unregister(blade_handle_t *bh, co
if (bhtr) ks_hash_remove(bh->transports, (void *)name);
ks_hash_write_unlock(bh->transports);
if (bhtr) blade_handle_transport_registration_destroy(&bhtr);
if (bhtr) {
blade_handle_transport_registration_destroy(&bhtr);
ks_log(KS_LOG_DEBUG, "Transport Unregistered: %s\n", name);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_handle_space_register(blade_space_t *bs)
{
blade_handle_t *bh = NULL;
const char *path = NULL;
blade_space_t *bs_old = NULL;
ks_assert(bs);
bh = blade_space_handle_get(bs);
ks_assert(bh);
path = blade_space_path_get(bs);
ks_assert(path);
ks_hash_write_lock(bh->spaces);
bs_old = ks_hash_search(bh->spaces, (void *)path, KS_UNLOCKED);
if (bs_old) ks_hash_remove(bh->spaces, (void *)path);
ks_hash_insert(bh->spaces, (void *)path, bs);
ks_hash_write_unlock(bh->spaces);
if (bs_old) blade_space_destroy(&bs_old);
ks_log(KS_LOG_DEBUG, "Space Registered: %s\n", path);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_handle_space_unregister(blade_space_t *bs)
{
blade_handle_t *bh = NULL;
const char *path = NULL;
ks_assert(bs);
bh = blade_space_handle_get(bs);
ks_assert(bh);
path = blade_space_path_get(bs);
ks_assert(path);
ks_hash_write_lock(bh->spaces);
bs = ks_hash_search(bh->spaces, (void *)path, KS_UNLOCKED);
if (bs) ks_hash_remove(bh->spaces, (void *)path);
ks_hash_write_unlock(bh->spaces);
if (bs) {
blade_space_destroy(&bs);
ks_log(KS_LOG_DEBUG, "Space Unregistered: %s\n", path);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(blade_space_t *) blade_handle_space_lookup(blade_handle_t *bh, const char *path)
{
blade_space_t *bs = NULL;
ks_assert(bh);
ks_assert(path);
ks_hash_read_lock(bh->spaces);
bs = ks_hash_search(bh->spaces, (void *)path, KS_UNLOCKED);
ks_hash_read_unlock(bh->spaces);
return bs;
}
KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connection_t **bcP, blade_identity_t *target, const char *session_id)
{
ks_status_t ret = KS_STATUS_SUCCESS;

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* 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 the original author; nor the names of any 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 "blade.h"
/*
Find bootstrap addr.
Make a WSS connection to get validated and get group keys.
Broadcast/Announce existence.
HEADER
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Ver |r|R|U|U| Channel no | Packet Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SEQ |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PAYLOAD ...... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
r = IS Response
R = IS Retransmission
U = Unused
PAYLOAD
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Instruction | Datatype | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PAYLOAD ..... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
typedef struct bpcp_header_s {
uint32_t header;
uint64_t seq;
} bpcp_header_t;
typedef struct bpcp_channel_nfo_s {
char *channel_name;
unsigned char key[crypto_generichash_BYTES];
uint32_t ttl;
} bpcp_channel_nfo_t;
typedef struct bpcp_handle_s {
ks_socket_t sock;
ks_sockaddr_t local_addr;
ks_sockaddr_t bootstrap_addr;
ks_hash_t *channel_nfo_hash;
} bpcp_handle_t;
KS_DECLARE(ks_status_t) bpcp_create(bpcp_handle_t **handle,
const char *local_addr, ks_port_t local_port,
const char *bootstrap_addr, ks_port_t bootstrap_port)
{
return KS_STATUS_SUCCESS;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,23 +1,23 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* 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 the original author; nor the names of any 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
@ -46,7 +46,8 @@
#include "blade_session.h"
#include "blade_protocol.h"
#include "blade_datastore.h"
#include "bpcp.h"
#include "blade_space.h"
#include "blade_method.h"
KS_BEGIN_EXTERN_C

View File

@ -1,23 +1,23 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* Copyright (c) 2017, Shane Bryldt
* 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 the original author; nor the names of any 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
@ -31,12 +31,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _BPCP_H_
#define _BPCP_H_
#ifndef _BLADE_METHOD_H_
#define _BLADE_METHOD_H_
#include <blade.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_method_create(blade_method_t **bmP, blade_space_t *bs, const char *name, blade_request_callback_t callback);
KS_DECLARE(ks_status_t) blade_method_destroy(blade_method_t **bmP);
KS_DECLARE(const char *) blade_method_name_get(blade_method_t *bm);
KS_DECLARE(blade_request_callback_t) blade_method_callback_get(blade_method_t *bm);
KS_END_EXTERN_C
#endif

View File

@ -36,10 +36,17 @@
#include <blade.h>
KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, blade_handle_t *bh, const char *session_id, cJSON *json);
KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP,
blade_handle_t *bh,
const char *session_id,
cJSON *json,
blade_response_callback_t callback);
KS_DECLARE(ks_status_t) blade_request_destroy(blade_request_t **breqP);
KS_DECLARE(ks_status_t) blade_response_create(blade_response_t **bresP, blade_handle_t *bh, const char *session_id, blade_request_t *breq, cJSON *json);
KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP);
KS_DECLARE(ks_status_t) blade_rpc_request_create(ks_pool_t *pool, cJSON **json, cJSON **params, const char **id, const char *method);
KS_DECLARE(ks_status_t) blade_rpc_response_create(ks_pool_t *pool, cJSON **json, cJSON **result, const char *id);
KS_DECLARE(ks_status_t) blade_rpc_error_create(ks_pool_t *pool, cJSON **json, cJSON **error, const char *id, int32_t code, const char *message);
KS_END_EXTERN_C
#endif

View File

@ -1,166 +0,0 @@
/*
* Copyright (c) 2017, FreeSWITCH LLC
* 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 the original author; nor the names of any 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.
*/
#ifndef _BLADE_RPCPROTO_H_
#define _BLADE_RPCPROTO_H_
#include <ks_rpcmessage.h>
#include <blade_types.h>
// temp typedefs to get compile going
//typedef struct blade_peer_s blade_peer_t;
//typedef struct blade_event_s blade_event_t;
#define KS_RPCMESSAGE_NAMESPACE_LENGTH 16
#define KS_RPCMESSAGE_COMMAND_LENGTH 238
#define KS_RPCMESSAGE_FQCOMMAND_LENGTH (KS_RPCMESSAGE_NAMESPACE_LENGTH+KS_RPCMESSAGE_COMMAND_LENGTH+1)
#define KS_RPCMESSAGE_VERSION_LENGTH 9
/*
* contents to add to the "blade" field in rpc
*/
typedef struct blade_rpc_fields_s {
const char *to;
const char *from;
const char *token;
} blade_rpc_fields_t;
enum jrpc_status_t {
JRPC_PASS = (1 << 0),
JRPC_SEND = (1 << 1),
JRPC_EXIT = (1 << 2),
JRPC_SEND_EXIT = JRPC_SEND + JRPC_EXIT,
JRPC_ERROR = (1 << 3)
};
typedef enum jrpc_status_t (*jrpc_func_t) (cJSON *request, cJSON **replyP);
/*
* setup
* -----
*/
KS_DECLARE(ks_status_t) blade_rpc_init(ks_pool_t *pool);
/*
* namespace and call back registration
* ------------------------------------
*/
KS_DECLARE(ks_status_t) blade_rpc_declare_namespace(char* namespace, const char* version);
KS_DECLARE(ks_status_t) blade_rpc_register_function(char* namespace,
char *command,
jrpc_func_t func,
jrpc_func_t respfunc);
KS_DECLARE(ks_status_t) blade_rpc_register_custom_request_function(char* namespace,
char *command,
jrpc_func_t prefix_func,
jrpc_func_t postfix_func);
KS_DECLARE(ks_status_t) blade_rpc_register_custom_response_function(char *namespace,
char *command,
jrpc_func_t prefix_func,
jrpc_func_t postfix_func);
KS_DECLARE(void) blade_rpc_remove_namespace(char* namespace);
/*
* template registration and inheritance
* -------------------------------------
*/
KS_DECLARE(ks_status_t) blade_rpc_declare_template(char* templatename, const char* version);
KS_DECLARE(ks_status_t)blade_rpc_register_template_function(char *name,
char *command,
jrpc_func_t func,
jrpc_func_t respfunc);
KS_DECLARE(ks_status_t)blade_rpc_inherit_template(char *namespace, char* template);
/*
* create a request message
*/
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_request(char *namespace,
char *method,
blade_rpc_fields_t* fields,
cJSON **paramsP,
cJSON **requestP);
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_response(cJSON *request,
cJSON **reply,
cJSON **response);
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_errorresponse(cJSON *request,
cJSON **reply,
cJSON **response);
KS_DECLARE(ks_status_t) blade_rpc_parse_message(cJSON *message,
char **namespace,
char **method,
char **version,
uint32_t *idP,
blade_rpc_fields_t **fieldsP);
/*
* peer create/destroy
* -------------------
*/
//KS_DECLARE(ks_status_t) blade_rpc_onconnect(ks_pool_t *pool, blade_peer_t* peer);
//KS_DECLARE(ks_status_t) blade_rpc_disconnect(blade_peer_t* peer);
/*
* send message
* ------------
*/
KS_DECLARE(ks_status_t) blade_rpc_write(char *sessionid, char* data, uint32_t size); //uuid_t ?
KS_DECLARE(ks_status_t) blade_rpc_write_json(cJSON* json);
/*
* process inbound message
* -----------------------
*/
KS_DECLARE(ks_status_t) blade_rpc_process_data(const uint8_t *data, ks_size_t size);
KS_DECLARE(ks_status_t) blade_rpc_process_jsonmessage(cJSON *request);
#endif

View File

@ -1,23 +1,23 @@
/*
* Copyright (c) 2017, Shane Bryldt
* 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 the original author; nor the names of any 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
@ -52,7 +52,7 @@ KS_DECLARE(void) blade_session_hangup(blade_session_t *bs);
KS_DECLARE(ks_bool_t) blade_session_terminating(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_connections_add(blade_session_t *bs, const char *id);
KS_DECLARE(ks_status_t) blade_session_connections_remove(blade_session_t *bs, const char *id);
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json);
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json, blade_response_callback_t callback);
KS_DECLARE(ks_status_t) blade_session_sending_push(blade_session_t *bs, cJSON *json);
KS_DECLARE(ks_status_t) blade_session_sending_pop(blade_session_t *bs, cJSON **json);
KS_DECLARE(ks_status_t) blade_session_receiving_push(blade_session_t *bs, cJSON *json);

View File

@ -1,23 +1,23 @@
/*
* Copyright (c) 2017, FreeSWITCH Solutions LLC
* Copyright (c) 2017, Shane Bryldt
* 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 the original author; nor the names of any 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
@ -31,56 +31,21 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _KS_RPCMESSAGE_H_
#define _KS_RPCMESSAGE_H_
#include "ks.h"
#ifndef _BLADE_SPACE_H_
#define _BLADE_SPACE_H_
#include <blade.h>
KS_BEGIN_EXTERN_C
#define KS_RPCMESSAGE_NAMESPACE_LENGTH 16
#define KS_RPCMESSAGE_COMMAND_LENGTH 238
#define KS_RPCMESSAGE_FQCOMMAND_LENGTH (KS_RPCMESSAGE_NAMESPACE_LENGTH+KS_RPCMESSAGE_COMMAND_LENGTH+1)
#define KS_RPCMESSAGE_VERSION_LENGTH 9
typedef uint32_t ks_rpcmessageid_t;
KS_DECLARE(void) ks_rpcmessage_init(ks_pool_t *pool);
KS_DECLARE(void*) ks_json_pool_alloc(ks_size_t size);
KS_DECLARE(void) ks_json_pool_free(void *ptr);
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_request(char *namespace,
char *method,
cJSON **paramsP,
cJSON **requestP);
KS_DECLARE(ks_size_t) ks_rpc_create_buffer(char *namespace,
char *method,
cJSON **paramsP,
ks_buffer_t *buffer);
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_response(
const cJSON *request,
cJSON **resultP,
cJSON **responseP);
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_errorresponse(
const cJSON *request,
cJSON **errorP,
cJSON **responseP);
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrequest(cJSON *msg);
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrpc(cJSON *msg);
KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, const char *path);
KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP);
KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs);
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs);
KS_DECLARE(ks_status_t) blade_space_methods_add(blade_space_t *bs, blade_method_t *bm);
KS_DECLARE(ks_status_t) blade_space_methods_remove(blade_space_t *bs, blade_method_t *bm);
KS_DECLARE(blade_method_t *) blade_space_methods_get(blade_space_t *bs, const char *name);
KS_END_EXTERN_C
#endif /* defined(_KS_RPCMESSAGE_H_) */
#endif
/* For Emacs:
* Local Variables:

View File

@ -50,6 +50,11 @@ KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_handle_transport_register(blade_handle_t *bh, blade_module_t *bm, const char *name, blade_transport_callbacks_t *callbacks);
KS_DECLARE(ks_status_t) blade_handle_transport_unregister(blade_handle_t *bh, const char *name);
KS_DECLARE(ks_status_t) blade_handle_space_register(blade_space_t *bs);
KS_DECLARE(ks_status_t) blade_handle_space_unregister(blade_space_t *bs);
KS_DECLARE(blade_space_t *) blade_handle_space_lookup(blade_handle_t *bh, const char *path);
KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connection_t **bcP, blade_identity_t *target, const char *session_id);
KS_DECLARE(blade_connection_t *) blade_handle_connections_get(blade_handle_t *bh, const char *cid);

View File

@ -47,6 +47,12 @@ typedef struct blade_connection_s blade_connection_t;
typedef struct blade_session_s blade_session_t;
typedef struct blade_request_s blade_request_t;
typedef struct blade_response_s blade_response_t;
typedef struct blade_space_s blade_space_t;
typedef struct blade_method_s blade_method_t;
typedef ks_bool_t (*blade_request_callback_t)(blade_request_t *breq);
typedef ks_bool_t (*blade_response_callback_t)(blade_response_t *bres);
typedef struct blade_datastore_s blade_datastore_t;
@ -147,6 +153,7 @@ struct blade_request_s {
cJSON *message;
const char *message_id; // pulled from message for easier keying
blade_response_callback_t callback;
// @todo ttl to wait for response before injecting an error response locally
// @todo rpc response callback
};

View File

@ -1,13 +1,8 @@
AM_CFLAGS += -I$(abs_top_srcdir)/src/include -g -ggdb -O0
AM_CFLAGS += -I$(abs_top_srcdir)/src/include -g -ggdb -O0
TEST_LDADD = $(abs_top_builddir)/libblade.la -lconfig -lm -lpthread
check_PROGRAMS =
check_PROGRAMS += testrpcproto
testrpcproto_SOURCES = testrpcproto.c tap.c
testrpcproto_CFLAGS = $(AM_CFLAGS)
testrpcproto_LDADD = $(TEST_LDADD)
check_PROGRAMS += testbuild
testbuild_SOURCES = testbuild.c tap.c
testbuild_CFLAGS = $(AM_CFLAGS)

View File

@ -1,724 +0,0 @@
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <blade_rpcproto.h>
#pragma GCC optimize ("O0")
ks_pool_t *pool;
ks_thread_pool_t *tpool;
static ks_thread_t *threads[10];
static char idbuffer[51];
static enum jrpc_status_t process_widget(cJSON *msg, cJSON **response)
{
printf("entering process_widget\n");
char *b0 = cJSON_PrintUnformatted(msg);
printf("Request: %s\n", b0);
ks_pool_free(pool, &b0);
cJSON *resp = cJSON_CreateObject();
cJSON_AddNumberToObject(resp, "code", 199);
//ks_rpcmessageid_t msgid = ks_rpcmessage_create_response(msg, &resp, response);
ks_rpcmessageid_t msgid = blade_rpc_create_response(msg, &resp, response);
char *b1 = cJSON_PrintUnformatted(*response); //(*response);
printf("Response: msgid %d\n%s\n", msgid, b1);
ks_pool_free(pool, &b1);
printf("exiting process_wombat\n");
return JRPC_SEND;
}
static enum jrpc_status_t process_widget_response(cJSON *request, cJSON **msg)
{
printf("entering process_widget_response\n");
printf("exiting process_widget_response\n");
return JRPC_PASS;
}
static enum jrpc_status_t process_wombat(cJSON *msg, cJSON **replyP)
{
printf("entering process_wombat\n");
char *b0 = cJSON_PrintUnformatted(msg);
printf("\nRequest: %s\n\n", b0);
ks_pool_free(pool, &b0);
cJSON *result = cJSON_CreateObject();
cJSON_AddNumberToObject(result, "code", 99);
cJSON *response;
// ks_rpcmessageid_t msgid = ks_rpcmessage_create_response(msg, &result, &response);
ks_rpcmessageid_t msgid = blade_rpc_create_response(msg, &result, &response);
cJSON *response_copy = cJSON_Duplicate(response, 1);
blade_rpc_process_jsonmessage(response_copy);
if (msgid != 0) {
char *b1 = cJSON_PrintUnformatted(response); //(*response);
printf("\nResponse: msgid %d\n%s\n\n", msgid, b1);
blade_rpc_write_json(response);
ks_pool_free(pool, &b1);
}
else {
printf("process_wombat: unable to create response \n");
return JRPC_ERROR;
}
blade_rpc_fields_t *r_fields;
char *r_method;
char *r_namespace;
char *r_version;
uint32_t r_id;
ks_status_t s1 = blade_rpc_parse_message(msg, &r_namespace, &r_method, &r_version, &r_id, &r_fields);
if (s1 == KS_STATUS_FAIL) {
printf("process_wombat: blade_rpc_parse_message failed\n");
return JRPC_ERROR;
}
printf("\nprocess_wombat: blade_rpc_parse_message namespace %s, method %s, id %d, version %s, to %s, from %s, token %s\n\n",
r_namespace, r_method, r_id, r_version,
r_fields->to, r_fields->from, r_fields->token);
cJSON *parms2 = NULL;
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
char token[] = "abcdefhgjojklmnopqrst";
blade_rpc_fields_t fields;
fields.to = to;
fields.from = from;
fields.token = token;
// msgid = ks_rpcmessage_create_request("app1", "widget", &parms2, replyP);
msgid = blade_rpc_create_request(r_namespace, r_method, &fields, NULL, replyP);
if (!msgid) {
printf("process wombat: create of next request failed\n");
return JRPC_ERROR;
}
b0 = cJSON_PrintUnformatted(*replyP);
if (!b0) {
printf("process wombat: create of next request cannot be formatted\n");
return JRPC_ERROR;
}
printf("\nprocess wombat: next request\n%s\n\n", b0);
printf("\n\nexiting process_wombat with a reply to send\n");
return JRPC_SEND;
}
static enum jrpc_status_t process_wombat_prerequest(cJSON *request, cJSON **msg)
{
printf("entering process_wombat_prerequest\n");
printf("exiting process_wombat_prerequest\n");
return JRPC_SEND;
}
static enum jrpc_status_t process_wombat_postrequest(cJSON *request, cJSON **msg)
{
printf("entering process_wombat_postrequest\n");
printf("exiting process_wombat_postrequest\n");
return JRPC_PASS;
}
static enum jrpc_status_t process_wombat_response(cJSON *request, cJSON **msg)
{
printf("entering process_wombat_response\n");
printf("exiting process_wombat_response\n");
return JRPC_PASS;
}
static enum jrpc_status_t process_wombat_preresponse(cJSON *request, cJSON **msg)
{
printf("entering process_wombat_preresponse\n");
cJSON *response = NULL;
cJSON *result = NULL;
cJSON *parms2 = NULL;
//ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "widget", &parms2, msg);
printf("exiting process_wombat_preresponse\n");
return JRPC_SEND;
}
static enum jrpc_status_t process_wombat_postresponse(cJSON *request, cJSON **msg)
{
printf("entering process_postwombat_response\n");
printf("exiting process_postwombat_response\n");
return JRPC_PASS;
}
static enum jrpc_status_t process_badbunny( cJSON *msg, cJSON **response)
{
printf("entering process_badbunny\n");
char *b0 = cJSON_PrintUnformatted(msg);
printf("\nRequest: %s\n\n", b0);
ks_pool_free(pool, &b0);
cJSON *respvalue;
ks_rpcmessageid_t msgid = ks_rpcmessage_create_errorresponse(msg, &respvalue, response);
char *b2 = cJSON_PrintUnformatted(*response);
printf("\nRequest: msgid %d\n%s\n\n", msgid, b2);
ks_pool_free(pool, &b2);
//cJSON *respvalue = cJSON_CreateNumber(1);
char *b1 = cJSON_PrintUnformatted(*response); //(*response);
printf("\nResponse: %s\n\n", b1);
ks_pool_free(pool, &b1);
printf("exiting process_badbunny\n");
return JRPC_SEND;
}
void test01()
{
printf("**** testrpcmessages - test01 start\n"); fflush(stdout);
blade_rpc_declare_template("temp1", "1.0");
blade_rpc_register_template_function("temp1", "widget", process_widget, process_widget_response);
blade_rpc_declare_namespace("app1", "1.0");
blade_rpc_register_function("app1", "wombat", process_wombat, process_wombat_response);
blade_rpc_register_custom_request_function("app1", "wombat", process_wombat_prerequest, process_wombat_postresponse);
blade_rpc_register_custom_response_function("app1", "wombat", process_wombat_preresponse, process_wombat_postresponse);
/* message 1 */
/* --------- */
cJSON* request1 = NULL;
cJSON* parms1 = NULL;
printf("\n\n\n - test01 message1 - basic message\n\n\n");
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "wombat", &parms1, &request1);
if (msgid == 0) {
printf("test01.1: unable to create message 1\n");
return;
}
if (!request1) {
printf("test01.1: No json returned from create request 1\n");
return;
}
cJSON_AddStringToObject(parms1, "hello", "cruel world");
char *pdata = cJSON_PrintUnformatted(request1);
if (!pdata) {
printf("test01.1: unable to parse cJSON object\n");
return;
}
printf("test01 request:\n%s\n", pdata);
blade_rpc_process_jsonmessage(request1);
cJSON_Delete(request1);
ks_pool_free(pool, &pdata);
printf("\ntest01.1 complete\n");
/* message 2 */
/* --------- */
printf("\n\n\n test01 - message2 - test inherit\n\n\n");
blade_rpc_inherit_template("app1", "temp1");
cJSON* request2 = NULL;
cJSON* parms2 = cJSON_CreateObject();
cJSON_AddStringToObject(parms2, "hello2", "cruel world once again");
msgid = ks_rpcmessage_create_request("app1", "temp1.widget", &parms2, &request2);
if (msgid == 0) {
printf("test01.2: failed to create a wombat\n");
return;
}
if (!request2) {
printf("test01.2: No json returned from create request 1\n");
return;
}
pdata = cJSON_PrintUnformatted(request2);
if (!pdata) {
printf("test01.2: unable to parse cJSON object\n");
return;
}
printf("\ntest01 request:\n%s\n\n\n", pdata);
blade_rpc_process_jsonmessage(request2);
cJSON_Delete(request2);
ks_pool_free(pool, &pdata);
printf("\ntest01.2 complete\n");
return;
}
void test02()
{
printf("**** testrpcmessages - test02 start\n"); fflush(stdout);
blade_rpc_declare_namespace("app2", "1.0");
blade_rpc_register_function("app2", "wombat", process_wombat, process_wombat_response);
blade_rpc_inherit_template("app2", "temp1");
blade_rpc_register_custom_request_function("app2", "wombat", process_wombat_prerequest, process_wombat_postresponse);
blade_rpc_register_custom_response_function("app2", "wombat", process_wombat_preresponse, process_wombat_postresponse);
blade_rpc_register_function("app2", "bunny", process_badbunny, NULL);
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
char token[] = "abcdefhgjojklmnopqrst";
blade_rpc_fields_t fields;
fields.to = to;
fields.from = from;
fields.token = token;
/* test the 4 different ways to handle param messages */
cJSON *params1 = NULL;
cJSON *request1;
ks_rpcmessageid_t msgid = blade_rpc_create_request("app2", "temp1.widget2", &fields, &params1, &request1);
if (!msgid) {
printf("test02.1: create_request failed\n");
return;
}
cJSON_AddStringToObject(params1, "hello", "cruel world");
char *pdata = cJSON_PrintUnformatted(request1);
if (!pdata) {
printf("test02.1: unable to parse cJSON object\n");
return;
}
printf("\ntest02.1 request:\n\n%s\n\n\n", pdata);
printf("\n\n -----------------------------------------\n\n");
ks_status_t s1 = blade_rpc_process_jsonmessage(request1);
if (s1 == KS_STATUS_FAIL) {
printf("test02.1: process request1 failed\n");
return;
}
printf(" -----------------------------------------\n\n\n\n");
ks_pool_free(pool, &pdata);
cJSON *reply1 = NULL;
cJSON *response1 = NULL;
ks_rpcmessageid_t msgid2 = blade_rpc_create_response(request1, &reply1, &response1);
if (!msgid2) {
printf("test02.1: create_response failed\n");
return;
}
cJSON_AddNumberToObject(reply1, "code", 10);
cJSON_AddStringToObject(reply1, "farewell", "cruel server");
pdata = cJSON_PrintUnformatted(response1);
if (!pdata) {
printf("test02.1: unable to parse cJSON response object\n");
return;
}
printf("\ntest02.1 response:\n\n%s\n\n\n", pdata);
printf("\n\n -----------------------------------------\n\n");
s1 = blade_rpc_process_jsonmessage(response1);
if (s1 == KS_STATUS_FAIL) {
printf("test02.1: process request1 failed\n");
return;
}
printf(" -----------------------------------------\n\n\n\n");
ks_pool_free(pool, &pdata);
printf("**** testrpcmessages - test02 finished\n"); fflush(stdout);
return;
}
void test02a()
{
printf("**** testrpcmessages - test02a start\n"); fflush(stdout);
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
char token[] = "abcdefhgjojklmnopqrst";
blade_rpc_fields_t fields;
fields.to = to;
fields.from = from;
fields.token = token;
/* test the 4 different ways to handle param messages */
cJSON *request1;
ks_rpcmessageid_t msgid = blade_rpc_create_request("app2", "wombat", &fields, NULL, &request1);
if (!msgid) {
printf("test02.1: create_request failed\n");
return;
}
char *pdata = cJSON_PrintUnformatted(request1);
if (!pdata) {
printf("test02.1: unable to parse cJSON object\n");
return;
}
printf("\ntest02.1 request:\n\n%s\n\n\n", pdata);
printf("\n\n -----------------------------------------\n\n");
ks_status_t s1 = blade_rpc_process_jsonmessage(request1);
if (s1 == KS_STATUS_FAIL) {
printf("test02.1: process request1 failed\n");
return;
}
printf(" -----------------------------------------\n\n\n\n");
ks_pool_free(pool, &pdata);
cJSON *response1 = NULL;
ks_rpcmessageid_t msgid2 = blade_rpc_create_response(request1, NULL, &response1);
if (!msgid2) {
printf("test02.1: create_response failed\n");
return;
}
pdata = cJSON_PrintUnformatted(response1);
printf("\ntest02.1 response:\n\n%s\n\n\n", pdata);
ks_pool_free(pool, &pdata);
printf("**** testrpcmessages - test02a finished\n\n\n"); fflush(stdout);
return;
}
void test02b()
{
printf("**** testrpcmessages - test02b start\n"); fflush(stdout);
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
char token[] = "abcdefhgjojklmnopqrst";
blade_rpc_fields_t fields;
fields.to = to;
fields.from = from;
fields.token = token;
/* test the 4 different ways to handle param messages */
cJSON *params1 = cJSON_CreateNumber(4321);
cJSON *request1;
ks_rpcmessageid_t msgid = blade_rpc_create_request("app2", "temp1.widget", &fields, &params1, &request1);
if (!msgid) {
printf("test02.1: create_request failed\n");
return;
}
char *pdata = cJSON_PrintUnformatted(request1);
if (!pdata) {
printf("test02.1: unable to parse cJSON object\n");
return;
}
printf("\ntest02.1 request:\n\n%s\n\n\n", pdata);
ks_pool_free(pool, &pdata);
cJSON *reply1 = cJSON_CreateString("successful");
cJSON *response1 = NULL;
ks_rpcmessageid_t msgid2 = blade_rpc_create_response(request1, &reply1, &response1);
if (!msgid2) {
printf("test02.1: create_response failed\n");
return;
}
pdata = cJSON_PrintUnformatted(response1);
printf("\ntest02.1 response:\n\n%s\n\n\n", pdata);
ks_pool_free(pool, &pdata);
printf("**** testrpcmessages - test02b finished\n"); fflush(stdout);
return;
}
void test02c()
{
printf("**** testrpcmessages - test02c start\n"); fflush(stdout);
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
char token[] = "abcdefhgjojklmnopqrst";
blade_rpc_fields_t fields;
fields.to = to;
fields.from = from;
fields.token = token;
/* test the 4 different ways to handle param messages */
cJSON *params1 = cJSON_CreateObject();
cJSON_AddStringToObject(params1, "string1", "here is a string");
cJSON_AddNumberToObject(params1, "number1", 4242);
cJSON *request1;
ks_rpcmessageid_t msgid = blade_rpc_create_request("app2", "bunny", &fields, &params1, &request1);
if (!msgid) {
printf("test02.1: create_request failed\n");
return;
}
cJSON_AddStringToObject(params1, "hello", "cruel world");
char *pdata = cJSON_PrintUnformatted(request1);
if (!pdata) {
printf("test02.1: unable to parse cJSON object\n");
return;
}
printf("\ntest02.1 request:\n\n%s\n\n\n", pdata);
ks_pool_free(pool, &pdata);
cJSON *reply1 = cJSON_CreateObject();
cJSON_AddNumberToObject(reply1, "code", 10);
cJSON_AddStringToObject(reply1, "farewell", "cruel server");
cJSON *response1 = NULL;
ks_rpcmessageid_t msgid2 = blade_rpc_create_response(request1, &reply1, &response1);
if (!msgid2) {
printf("test02.1: create_response failed\n");
return;
}
pdata = cJSON_PrintUnformatted(response1);
printf("\ntest02.1 response:\n\n%s\n\n\n", pdata);
ks_pool_free(pool, &pdata);
printf("**** testrpcmessages - test02c finished\n"); fflush(stdout);
return;
}
/* test06 */
/* ------ */
static void *testnodelocking_ex1(ks_thread_t *thread, void *data)
{
return NULL;
}
static void *testnodelocking_ex2(ks_thread_t *thread, void *data)
{
return NULL;
}
void test06()
{
printf("**** testmessages - test06 start\n"); fflush(stdout);
ks_thread_t *t0;
ks_thread_create(&t0, testnodelocking_ex1, NULL, pool);
ks_thread_t *t1;
ks_thread_create(&t1, testnodelocking_ex2, NULL, pool);
ks_thread_join(t1);
ks_thread_join(t0);
printf("\n\n* **testmessages - test06 -- threads complete\n\n"); fflush(stdout);
printf("**** testmessages - test06 start\n"); fflush(stdout);
return;
}
int main(int argc, char *argv[]) {
printf("testmessages - start\n");
int tests[100];
if (argc == 0) {
tests[0] = 1;
tests[1] = 2;
tests[2] = 3;
tests[3] = 4;
tests[4] = 5;
}
else {
for(int tix=1; tix<100 && tix<argc; ++tix) {
long i = strtol(argv[tix], NULL, 0);
tests[tix] = i;
}
}
ks_init();
ks_global_set_default_logger(7);
ks_status_t status;
status = ks_pool_open(&pool);
blade_rpc_init(pool);
blade_rpc_declare_template("temp1", "1.0");
blade_rpc_register_template_function("temp1", "widget", process_widget, process_widget_response);
blade_rpc_register_template_function("temp1", "widget2", process_widget, process_widget_response);
blade_rpc_register_template_function("temp1", "widget3", process_widget, process_widget_response);
for (int tix=0; tix<argc; ++tix) {
if (tests[tix] == 1) {
test01();
continue;
}
if (tests[tix] == 2) {
test02();
printf("\n\n");
test02a();
printf("\n\n");
test02b();
printf("\n\n");
test02c();
printf("\n\n");
continue;
}
}
return 0;
}

View File

@ -10,13 +10,13 @@ lib_LTLIBRARIES = libks.la
libks_la_SOURCES = src/ks.c src/ks_string.c src/ks_json.c src/cJSON.c src/cJSON_Utils.c src/ks_thread.c src/ks_thread_pool.c src/ks_mutex.c src/ks_config.c
libks_la_SOURCES += src/ks_log.c src/ks_socket.c src/ks_buffer.c src/ks_pool.c src/simclist.c
libks_la_SOURCES += src/ks_time.c src/ks_printf.c src/ks_hash.c src/ks_q.c src/ks_dso.c # src/ks_dht.c
libks_la_SOURCES += src/ks_ssl.c src/kws.c src/ks_rng.c src/ks_rpcmessage.c src/ks_base64.c
libks_la_SOURCES += src/ks_ssl.c src/kws.c src/ks_rng.c src/ks_base64.c
libks_la_SOURCES += src/utp/utp_api.cpp src/utp/utp_callbacks.cpp src/utp/utp_hash.cpp src/utp/utp_internal.cpp
libks_la_SOURCES += src/utp/utp_packedsockaddr.cpp src/utp/utp_utils.cpp src/ks_bencode.c
libks_la_SOURCES += src/dht/ks_dht.c src/dht/ks_dht_datagram.c src/dht/ks_dht_endpoint.c src/dht/ks_dht_message.c src/dht/ks_dht_transaction.c
libks_la_SOURCES += src/dht/ks_dht_job.c src/dht/ks_dht_search.c src/dht/ks_dht_publish.c src/dht/ks_dht_distribute.c src/dht/ks_dht_storageitem.c
libks_la_SOURCES += src/dht/ks_dht_bucket.c
libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c
libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c
#aes.h aescpp.h brg_endian.h aesopt.h aestab.h brg_types.h sha2.h twofish.h
libks_la_SOURCES += src/ks_acl.c
@ -29,14 +29,10 @@ library_include_HEADERS = src/include/ks_config.h src/include/ks.h src/include/k
library_include_HEADERS += src/include/ks_thread_pool.h src/include/ks_cJSON.h src/include/ks_cJSON_Utils.h
library_include_HEADERS += src/include/ks_pool.h src/include/simclist.h src/include/ks_time.h src/include/ks_q.h src/include/ks_socket.h
library_include_HEADERS += src/include/ks_dso.h src/include/ks_platform.h src/include/ks_types.h # src/include/ks_rng.h src/include/ks_dht.h
library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
library_include_HEADERS += src/include/ks_rpcmessage.h src/include/ks_base64.h
library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
library_include_HEADERS += src/include/ks_base64.h
library_include_HEADERS += src/utp/utp_internal.h src/utp/utp.h src/utp/utp_types.h src/utp/utp_callbacks.h src/utp/utp_templates.h
library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h src/include/ks_acl.h
tests: libks.la
$(MAKE) -C test tests

View File

@ -1,23 +1,23 @@
/*
* Copyright (c) 2007-2014, Anthony Minessale II
* 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 the original author; nor the names of any 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
@ -137,7 +137,6 @@ KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
#include "ks_bencode.h"
#include "ks_rng.h"
#include "ks_acl.h"
#include "ks_rpcmessage.h"
#include "ks_base64.h"
KS_END_EXTERN_C

View File

@ -1,317 +0,0 @@
/*
* Copyright (c) 2017 FreeSWITCH Solutions LLC
* 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 the original author; nor the names of any 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.
*/
#pragma GCC optimize ("O0")
#include <ks.h>
#include <ks_rpcmessage.h>
#include <ks_buffer.h>
struct
{
ks_mutex_t *id_mutex;
uint32_t message_id;
ks_pool_t *pool;
} handle = {NULL, 0, NULL};
const char PROTOCOL[] = "jsonrpc";
const char PROTOCOL_VERSION[] = "2.0";
const char ID[] = "id";
const char METHOD[] = "method";
const char PARAMS[] = "params";
const char ERROR[] = "error";
const char RESULT[] = "result";
KS_DECLARE(void*) ks_json_pool_alloc(ks_size_t size)
{
return ks_pool_alloc(handle.pool, size);
}
KS_DECLARE(void) ks_json_pool_free(void *ptr)
{
ks_pool_free(handle.pool, &ptr);
}
KS_DECLARE(void) ks_rpcmessage_init(ks_pool_t* pool)
{
if (!handle.id_mutex) {
ks_mutex_create(&handle.id_mutex, KS_MUTEX_FLAG_DEFAULT, pool);
handle.pool = pool;
cJSON_Hooks hooks;
hooks.malloc_fn = ks_json_pool_alloc;
hooks.free_fn = ks_json_pool_free;
cJSON_InitHooks(&hooks);
}
return;
}
static uint32_t ks_rpcmessage_next_id()
{
uint32_t message_id;
ks_mutex_lock(handle.id_mutex);
++handle.message_id;
if (!handle.message_id) {
++handle.message_id;
}
message_id = handle.message_id;
ks_mutex_unlock(handle.id_mutex);
return message_id;
}
static cJSON *ks_rpcmessage_new(uint32_t id)
{
cJSON *obj = cJSON_CreateObject();
cJSON_AddItemToObject(obj, PROTOCOL, cJSON_CreateString(PROTOCOL_VERSION));
if (id) {
cJSON_AddItemToObject(obj, ID, cJSON_CreateNumber(id));
}
return obj;
}
static cJSON *ks_rpcmessage_dup(cJSON *msgid)
{
cJSON *obj = cJSON_CreateObject();
cJSON_AddItemToObject(obj, PROTOCOL, cJSON_CreateString(PROTOCOL_VERSION));
if (msgid) {
cJSON_AddItemToObject(obj, ID, cJSON_Duplicate(msgid, 0));
}
return obj;
}
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrequest(cJSON *msg)
{
cJSON *result = cJSON_GetObjectItem(msg, RESULT);
cJSON *error = cJSON_GetObjectItem(msg, ERROR);
if (result || error) {
return KS_FALSE;
}
return KS_TRUE;
}
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrpc(cJSON *msg)
{
cJSON *rpc = cJSON_GetObjectItem(msg, PROTOCOL);
if (rpc) {
return KS_FALSE;
}
return KS_TRUE;
}
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_request(char *namespace,
char *command,
cJSON **paramsP,
cJSON **requestP)
{
cJSON *msg, *params = NULL;
*requestP = NULL;
ks_rpcmessageid_t msgid = ks_rpcmessage_next_id();
msg = ks_rpcmessage_new(msgid);
if (paramsP) {
if (*paramsP) { /* parameters have been passed */
params = *paramsP;
}
else {
params = cJSON_CreateObject();
*paramsP = params;
}
cJSON_AddItemToObject(msg, PARAMS, params);
}
char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
memset(fqcommand, 0, sizeof(fqcommand));
sprintf(fqcommand, "%s.%s", namespace, command);
cJSON_AddItemToObject(msg, METHOD, cJSON_CreateString(fqcommand));
*requestP = msg;
return msgid;
}
KS_DECLARE(ks_size_t) ks_rpc_create_buffer(char *namespace,
char *method,
cJSON **params,
ks_buffer_t *buffer)
{
cJSON *message;
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request(namespace, method, params, &message);
if (!msgid) {
return 0;
}
if ( (*params)->child == NULL) {
cJSON_AddNullToObject(*params, "bladenull");
}
const char* b = cJSON_PrintUnformatted(message);
ks_size_t size = strlen(b);
ks_buffer_write(buffer, b, size);
cJSON_Delete(message);
return size;
}
static ks_rpcmessageid_t ks_rpcmessage_get_messageid(const cJSON *msg, cJSON **cmsgidP)
{
ks_rpcmessageid_t msgid = 0;
cJSON *cmsgid = cJSON_GetObjectItem(msg, ID);
if (cmsgid->type == cJSON_Number) {
msgid = (ks_rpcmessageid_t) cmsgid->valueint;
}
*cmsgidP = cmsgid;
return msgid;
}
static ks_rpcmessageid_t ks_rpcmessage_new_response(
const cJSON *request,
cJSON **result,
cJSON **pmsg)
{
cJSON *respmsg = NULL;
cJSON *cmsgid = NULL;
cJSON *command = cJSON_GetObjectItem(request, METHOD);
ks_rpcmessageid_t msgid = ks_rpcmessage_get_messageid(request, &cmsgid );
if (!msgid || !command) {
return 0;
}
*pmsg = respmsg = ks_rpcmessage_dup(cmsgid);
cJSON_AddItemToObject(respmsg, METHOD, cJSON_Duplicate(command, 0));
if (result && *result) {
cJSON_AddItemToObject(respmsg, RESULT, *result);
}
return msgid;
}
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_response(
const cJSON *request,
cJSON **resultP,
cJSON **responseP)
{
ks_rpcmessageid_t msgid = ks_rpcmessage_new_response(request, resultP, responseP);
cJSON *respmsg = *responseP;
if (msgid) {
if (resultP && *resultP == NULL) {
cJSON *result = cJSON_CreateObject();
*resultP = result;
cJSON_AddItemToObject(respmsg, RESULT, result);
}
}
return msgid;
}
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_errorresponse(
const cJSON *request,
cJSON **errorP,
cJSON **responseP)
{
ks_rpcmessageid_t msgid = ks_rpcmessage_new_response(request, NULL, responseP);
cJSON *respmsg = *responseP;
if (msgid) {
if (errorP && *errorP == NULL) {
cJSON *error = cJSON_CreateObject();
*errorP = error;
cJSON_AddItemToObject(respmsg, ERROR, error);
}
else if (errorP && *errorP) {
cJSON_AddItemToObject(*responseP, ERROR, *errorP);
}
}
return msgid;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
*/

View File

@ -1,14 +1,9 @@
AM_CFLAGS += -I$(abs_top_srcdir)/src/include -g -ggdb -O0 $(openssl_CFLAGS)
TEST_LDADD = $(abs_top_builddir)/libks.la $(openssl_LIBS)
check_PROGRAMS =
check_PROGRAMS =
EXTRA_DIST = tap.h
check_PROGRAMS += testmessages
testmessages_SOURCES = testmessages.c tap.c
testmessages_CFLAGS = $(AM_CFLAGS)
testmessages_LDADD = $(TEST_LDADD)
check_PROGRAMS += testbuckets
testbuckets_SOURCES = testbuckets.c tap.c
testbuckets_CFLAGS = $(AM_CFLAGS)
@ -96,7 +91,7 @@ nodeidgen_LDADD = $(TEST_LDADD)
#check_PROGRAMS += libtorrent_example
#libtorrent_example_SOURCES = libtorrent-example.c
#libtorrent_example_CFLAGS = $(AM_CFLAGS)
#libtorrent_example_CFLAGS = $(AM_CFLAGS)
#libtorrent_example_LDADD = $(abs_top_builddir)/libks.la $(abs_top_builddir)/test/libtorrent.so /usr/lib/x86_64-linux-gnu/libboost_system.a $(openssl_LIBS) -ledit -lpthread -ltorrent-rasterbar -lstdc++
TESTS=$(check_PROGRAMS)
@ -108,4 +103,3 @@ $(abs_top_builddir)/test/libtorrent.so: $(abs_top_builddir)/test/libtorrent.o
$(abs_top_builddir)/test/libtorrent.o: $(abs_top_builddir)/test/libtorrent.cpp
g++ -c -fPIC -o $(abs_top_builddir)/test/libtorrent.o -I$(abs_top_builddir)/test/ $(abs_top_builddir)/test/libtorrent.cpp

View File

@ -1,124 +0,0 @@
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "../src/include/ks_rpcmessage.h"
#pragma GCC optimize ("O0")
ks_pool_t *pool;
void test01()
{
printf("**** testrpcmessages - test01 start\n\n"); fflush(stdout);
cJSON* request1 = NULL;
cJSON* parms1 = NULL;
cJSON* response1 = NULL;
/*namespace, method, params, **request */
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "func1", &parms1, &request1);
if (msgid == 0) {
printf("message create failed %d\n", msgid);
}
cJSON_AddStringToObject(parms1, "hello", "cruel world");
char* data = cJSON_PrintUnformatted(request1);
printf("test01 request1: %d\n%s\n\n", msgid, data);
ks_json_pool_free(data);
/* convert to buffer */
cJSON* parms2 = NULL;
ks_buffer_t *buffer;
ks_buffer_create(&buffer, 256, 256, 1024);
ks_size_t n = ks_rpc_create_buffer("app2", "func2", &parms2, buffer);
ks_size_t size = ks_buffer_len(buffer);
char *b = (char *)ks_pool_alloc(pool, size+1);
ks_buffer_read(buffer, b, size);
printf("test01 request2: %zd %zd from ks_buffer\n%s\n\n\n", n, size, b);
/* create message 3 */
cJSON *parms3 = cJSON_CreateNumber(1);
cJSON *request3 = NULL;
msgid = ks_rpcmessage_create_request("app1", "badbunny", &parms3, &request3);
data = cJSON_PrintUnformatted(request3);
printf("\ntest01i request: %d\n%s\n\n", msgid, data);
cJSON *response3 = NULL;
ks_rpcmessage_create_response(request3, NULL, &response3);
data = cJSON_PrintUnformatted(response3);
printf("\ntest01 response3: %d\n%s\n\n", msgid, data);
ks_json_pool_free(data);
cJSON_Delete(request3);
cJSON_Delete(response3);
printf("**** testrpcmessages - test01 complete\n\n\n"); fflush(stdout);
}
void test02()
{
printf("**** testmessages - test02 start\n"); fflush(stdout);
printf("**** testmessages - test02 finished\n"); fflush(stdout);
return;
}
int main(int argc, char *argv[]) {
printf("testmessages - start\n");
int tests[100];
if (argc == 1) {
tests[0] = 1;
}
else {
for(int tix=1; tix<100 && tix<argc; ++tix) {
long i = strtol(argv[tix], NULL, 0);
tests[tix] = i;
}
}
ks_init();
ks_global_set_default_logger(7);
ks_status_t status;
status = ks_pool_open(&pool);
for (int tix=0; tix<argc; ++tix) {
if (tests[tix] == 1) {
ks_rpcmessage_init(pool);
test01();
continue;
}
if (tests[tix] == 2) {
ks_rpcmessage_init(pool);
test02();
continue;
}
}
return 0;
}