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
-
-
-
-
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);
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);
--- /dev/null
+/*
+ * 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:
+ */
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);
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 =
{
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,
};
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);
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;
{
blade_module_wss_t *bm_wss = NULL;
blade_connection_t *bc = NULL;
+ ks_bool_t stopped = KS_FALSE;
ks_assert(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) {
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;
}
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);
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)
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;
{
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;
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) {
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;
}
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;
}
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;
}
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);
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;
}
// @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;
}
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;
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;
}
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;
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);
+
+ 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_detach_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
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_ready_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
{
ks_assert(bc);
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
#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;
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;
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;
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:
+++ /dev/null
-/*
- * 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 <blade_rpcproto.h>
-
-/*
- * internal shared structure grounded in global
- */
-typedef struct blade_rpc_handle_ex {
-
- ks_hash_t *namespace_hash; /* hash to namespace methods */
- ks_hash_t *template_hash; /* hash to template methods */
-
- ks_hash_t *peer_hash; /* hash to peer structure */
-
- ks_q_t *event_queue;
- ks_bool_t isactive;
- ks_pool_t *pool;
-
-} blade_rpc_handle_ex_t;
-
-
-typedef struct blade_rpc_namespace_s {
-
- char name[KS_RPCMESSAGE_NAMESPACE_LENGTH+1];
- char version[KS_RPCMESSAGE_VERSION_LENGTH+1]; /* nnn.nn.nn */
- ks_hash_t *method_hash; /* hash to namespace methods */
-
-} blade_rpc_namespace_t;
-
-
-
-
-blade_rpc_handle_ex_t *g_handle = NULL;
-
-
-/*
- * callbacks - from blade_rpc_handle_ex->method_hash
- */
-
-typedef struct blade_rpc_custom_callbackpair_s
-{
- jrpc_func_t prefix_request_func;
- jrpc_func_t postfix_request_func;
-
- jrpc_func_t prefix_response_func;
- jrpc_func_t postfix_response_func;
-
-} blade_rpc_custom_callbackpair_t;
-
-
-
-typedef struct blade_rpc_callbackpair_s
-{
- jrpc_func_t request_func;
-
- jrpc_func_t response_func;
-
- blade_rpc_custom_callbackpair_t* custom;
-
- ks_mutex_t *lock;
-
- uint16_t command_length;
- char command[1];
-
-} blade_rpc_callbackpair_t;
-
-
-
-
-
-static void blade_rpc_make_fqcommand(const char* namespace, const char *command, char *fscommand)
-{
- memset(fscommand, 0, KS_RPCMESSAGE_FQCOMMAND_LENGTH);
- sprintf(fscommand, "%s.%s", namespace, command);
-
- return;
-}
-
-static void blade_rpc_parse_fqcommand(const char* fscommand, char *namespace, char *command)
-{
- memset(command, 0, KS_RPCMESSAGE_COMMAND_LENGTH);
- memset(namespace, 0, KS_RPCMESSAGE_NAMESPACE_LENGTH);
-
- uint32_t len = strlen(fscommand);
-
- assert(len <= KS_RPCMESSAGE_FQCOMMAND_LENGTH);
- ks_bool_t dotfound = KS_FALSE;
-
- for(int i=0, x=0; i<len; ++i, ++x) {
-
- if (fscommand[i] == '.' && dotfound == KS_FALSE) {
- dotfound = KS_TRUE;
- x = -1;
- }
- else if (dotfound == KS_FALSE) {
- namespace[x] = fscommand[i];
- }
- else {
- command[x] = fscommand[i];
- }
-
- }
-
- return;
-}
-
-
-
-KS_DECLARE(ks_status_t) blade_rpc_init(ks_pool_t *pool)
-{
- if (g_handle == NULL) {
- g_handle = ks_pool_alloc(pool, sizeof(blade_rpc_handle_ex_t));
- ks_hash_create(&g_handle->namespace_hash,
- KS_HASH_MODE_CASE_SENSITIVE,
- KS_HASH_FLAG_RWLOCK + KS_HASH_FLAG_DUP_CHECK, // + KS_HASH_FLAG_FREE_VALUE,
- pool);
-
- ks_hash_create(&g_handle->template_hash,
- KS_HASH_MODE_CASE_SENSITIVE,
- KS_HASH_FLAG_RWLOCK + KS_HASH_FLAG_DUP_CHECK, // + KS_HASH_FLAG_FREE_VALUE,
- pool);
-
- ks_q_create(&g_handle->event_queue, pool, 1024);
-
- g_handle->pool = pool;
-
- /* initialize rpc messaging mechanism */
- ks_rpcmessage_init(pool);
-
- g_handle->isactive = KS_TRUE;
- }
- return KS_STATUS_SUCCESS;
-}
-
-
-//KS_DECLARE(ks_status_t) blade_rpc_onconnect(ks_pool_t *pool, blade_peer_t* peer)
-//{
-//
-//
-// return KS_STATUS_FAIL;
-//}
-//
-//KS_DECLARE(ks_status_t) blade_rpc_disconnect(blade_peer_t* peer)
-//{
-//
-// return KS_STATUS_FAIL;
-//}
-
-
-
-/*
- * namespace setup
- */
-
-/*
- * function/callback functions
- */
-static blade_rpc_callbackpair_t *blade_rpc_find_callbacks_locked(char *namespace, char *command)
-{
- blade_rpc_callbackpair_t *callbacks = NULL;
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, namespace, KS_UNLOCKED);
- if (n) {
-
- ks_hash_read_lock(n->method_hash);
-
- callbacks = ks_hash_search(n->method_hash, command, KS_UNLOCKED);
-
- if (callbacks) {
- ks_mutex_lock(callbacks->lock);
- }
-
- ks_hash_read_unlock(n->method_hash);
- }
-
- return callbacks;
-}
-
-static blade_rpc_callbackpair_t *blade_rpc_find_template_locked(char *name, char *command)
-{
- blade_rpc_callbackpair_t *callbacks = NULL;
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->template_hash, name, KS_UNLOCKED);
- if (n) {
-
- ks_hash_read_lock(n->method_hash);
- callbacks = ks_hash_search(n->method_hash, command, KS_UNLOCKED);
-
- if (callbacks) {
- ks_mutex_lock(callbacks->lock);
- }
-
- ks_hash_read_unlock(n->method_hash);
- }
-
- return callbacks;
-}
-
-
-
-
-static blade_rpc_callbackpair_t *blade_rpc_find_callbacks_locked_fq(char *fqcommand)
-{
- blade_rpc_callbackpair_t *callbacks = NULL;
-
- char command[KS_RPCMESSAGE_COMMAND_LENGTH+1];
- char namespace[KS_RPCMESSAGE_NAMESPACE_LENGTH+1];
-
- blade_rpc_parse_fqcommand(fqcommand, namespace, command);
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, namespace, KS_UNLOCKED);
- if (n) {
- blade_rpc_make_fqcommand(namespace, command, fqcommand);
- ks_hash_read_lock(n->method_hash);
-
- callbacks = ks_hash_search(n->method_hash, fqcommand, KS_UNLOCKED);
-
- if (callbacks) {
- ks_mutex_lock(callbacks->lock);
- }
-
- ks_hash_read_unlock(n->method_hash);
- }
-
- return callbacks;
-}
-
-
-KS_DECLARE(jrpc_func_t) blade_rpc_find_request_function(char *fqcommand)
-{
-
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked_fq(fqcommand);
-
- if (!callbacks) {
- return NULL;
- }
-
- jrpc_func_t f = callbacks->request_func;
-
- ks_mutex_unlock(callbacks->lock);
-
- return f;
-}
-
-KS_DECLARE(jrpc_func_t) blade_rpc_find_requestprefix_function(char *fqcommand)
-{
-
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked_fq(fqcommand);
-
- if (!callbacks || !callbacks->custom) {
- return NULL;
- }
-
- jrpc_func_t f = callbacks->custom->prefix_request_func;
-
- ks_mutex_unlock(callbacks->lock);
-
- return f;
-}
-
-KS_DECLARE(jrpc_func_t) blade_rpc_find_response_function(char *fqcommand)
-{
-
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked_fq(fqcommand);
-
- if (!callbacks) {
- return NULL;
- }
-
- jrpc_func_t f = callbacks->response_func;
-
- ks_mutex_unlock(callbacks->lock);
-
- return f;
-}
-
-KS_DECLARE(jrpc_func_t) blade_rpc_find_responseprefix_function(char *fqcommand)
-{
-
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked_fq(fqcommand);
-
- if (!callbacks || !callbacks->custom) {
- return NULL;
- }
-
- jrpc_func_t f = callbacks->custom->prefix_response_func;
-
- ks_mutex_unlock(callbacks->lock);
-
- return f;
-}
-
-
-KS_DECLARE(ks_status_t) blade_rpc_declare_namespace(char* namespace, const char* version)
-{
-
- /* find/insert to namespace hash as needed */
- ks_hash_write_lock(g_handle->namespace_hash);
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, namespace, KS_UNLOCKED);
- if (n == NULL) {
- n = ks_pool_alloc(g_handle->pool, sizeof (blade_rpc_namespace_t) + strlen(namespace) + 1);
- strncpy(n->name, namespace, KS_RPCMESSAGE_NAMESPACE_LENGTH);
- strncpy(n->version, version, KS_RPCMESSAGE_VERSION_LENGTH);
- ks_hash_create(&n->method_hash,
- KS_HASH_MODE_CASE_SENSITIVE,
- KS_HASH_FLAG_RWLOCK + KS_HASH_FLAG_DUP_CHECK + KS_HASH_FLAG_FREE_VALUE,
- g_handle->pool);
- ks_hash_insert(g_handle->namespace_hash, n->name, n);
- }
- ks_hash_write_unlock(g_handle->namespace_hash);
-
- ks_log(KS_LOG_DEBUG, "Setting message namespace value %s, version %s\n", namespace, version);
-
- return KS_STATUS_SUCCESS;
-}
-
-
-KS_DECLARE(ks_status_t)blade_rpc_register_function(char *namespace,
- char *command,
- jrpc_func_t func,
- jrpc_func_t respfunc)
-{
- if (!func && !respfunc) {
- return KS_STATUS_FAIL;
- }
-
- char nskey[KS_RPCMESSAGE_NAMESPACE_LENGTH+1];
- memset(nskey, 0, sizeof(nskey));
- strcpy(nskey, namespace);
-
- char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
- memset(fqcommand, 0, sizeof(fqcommand));
-
-// strcpy(fqcommand, namespace);
-// strcpy(fqcommand, ".");
- strcat(fqcommand, command);
-
- int lkey = strlen(command)+1;
-
- if (lkey < 16) {
- lkey = 16;
- }
-
- ks_hash_read_lock(g_handle->namespace_hash); /* lock namespace hash */
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, nskey, KS_UNLOCKED);
-
- if (n == NULL) {
- ks_hash_read_unlock(g_handle->namespace_hash);
- ks_log(KS_LOG_ERROR, "Unable to find %s namespace\n", namespace);
- return KS_STATUS_FAIL;
- }
-
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked(nskey, command);
-
- /* just ignore attempt to re register callbacks */
- /* @todo : should this be smarter, allow override ? */
- if (callbacks != NULL) {
- ks_mutex_unlock(callbacks->lock);
- ks_hash_read_unlock(g_handle->namespace_hash);
- ks_log(KS_LOG_ERROR, "Callbacks already registered for %s namespace\n", namespace);
- return KS_STATUS_FAIL;
- }
-
- callbacks =
- (blade_rpc_callbackpair_t*)ks_pool_alloc(g_handle->pool, lkey + sizeof(blade_rpc_callbackpair_t));
-
- strcpy(callbacks->command, command);
- callbacks->command_length = lkey;
- callbacks->request_func = func;
- callbacks->response_func = respfunc;
- ks_mutex_create(&callbacks->lock, KS_MUTEX_FLAG_DEFAULT, g_handle->pool);
-
- ks_hash_write_lock(n->method_hash); /* lock method hash */
-
- ks_hash_insert(n->method_hash, callbacks->command, (void *) callbacks);
-
- ks_hash_write_unlock(n->method_hash); /* unlock method hash */
- ks_hash_read_unlock(g_handle->namespace_hash); /* unlock namespace hash */
-
- ks_log(KS_LOG_DEBUG, "Message %s %s registered\n", namespace, command);
-
- return KS_STATUS_SUCCESS;
-
-}
-
-
-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_status_t s = KS_STATUS_FAIL;
-
- char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
- memset(fqcommand, 0, sizeof(fqcommand));
- strcat(fqcommand, command);
-
- ks_hash_write_lock(g_handle->namespace_hash);
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked(namespace, fqcommand);
-
- if (callbacks) {
-
- if (!callbacks->custom) {
- callbacks->custom =
- (blade_rpc_custom_callbackpair_t *)ks_pool_alloc(g_handle->pool, sizeof(blade_rpc_custom_callbackpair_t));
- }
-
- callbacks->custom->prefix_request_func = prefix_func;
- callbacks->custom->postfix_request_func = postfix_func;
- ks_mutex_unlock(callbacks->lock);
- s = KS_STATUS_SUCCESS;
- }
-
- ks_hash_write_unlock(g_handle->namespace_hash);
- return s;
-}
-
-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_status_t s = KS_STATUS_FAIL;
-
- char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
- memset(fqcommand, 0, sizeof(fqcommand));
- strcat(fqcommand, command);
-
- ks_hash_write_lock(g_handle->namespace_hash);
- blade_rpc_callbackpair_t *callbacks = blade_rpc_find_callbacks_locked(namespace, fqcommand);
-
- if (callbacks) {
-
- if (!callbacks->custom) {
- callbacks->custom =
- (blade_rpc_custom_callbackpair_t *)ks_pool_alloc(g_handle->pool, sizeof(blade_rpc_custom_callbackpair_t));
- }
-
- callbacks->custom->prefix_response_func = prefix_func;
- callbacks->custom->postfix_response_func = postfix_func;
- ks_mutex_unlock(callbacks->lock);
- s = KS_STATUS_SUCCESS;
- }
-
- ks_hash_write_unlock(g_handle->namespace_hash);
- return s;
-}
-
-KS_DECLARE(void) blade_rpc_remove_namespace(char* namespace)
-{
- char nskey[KS_RPCMESSAGE_NAMESPACE_LENGTH];
- memset(nskey, 0, sizeof(nskey));
- strcat(nskey, namespace);
-
- ks_hash_write_lock(g_handle->namespace_hash);
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, nskey, KS_UNLOCKED);
-
- ks_hash_iterator_t* it = ks_hash_first(n->method_hash, KS_HASH_FLAG_RWLOCK);
-
- while (it) {
-
- const void *key;
- void *value;
- ks_ssize_t len = strlen(key);
-
- ks_hash_this(it, &key, &len, &value);
- blade_rpc_callbackpair_t *callbacks = (blade_rpc_callbackpair_t *)value;
-
- ks_mutex_lock(callbacks->lock);
-
- if (callbacks->custom) {
- ks_pool_free(g_handle->pool, callbacks->custom);
- }
-
- it = ks_hash_next(&it);
- ks_hash_remove(n->method_hash, (void *)key);
- }
-
- ks_hash_write_unlock(g_handle->namespace_hash);
-
- return;
-}
-
-
-/*
- * template functions
- *
- */
-
-KS_DECLARE(ks_status_t) blade_rpc_declare_template(char* templatename, const char* version)
-{
- char nskey[KS_RPCMESSAGE_NAMESPACE_LENGTH];
- memset(nskey, 0, sizeof(nskey));
- strcat(nskey, templatename);
-
-
- /* find/insert to namespace hash as needed */
- ks_hash_write_lock(g_handle->template_hash);
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->template_hash, nskey, KS_UNLOCKED);
-
- if (n == NULL) {
- n = ks_pool_alloc(g_handle->pool, sizeof (blade_rpc_namespace_t) + strlen(templatename) + 1);
- strncpy(n->name, templatename, KS_RPCMESSAGE_NAMESPACE_LENGTH);
- strncpy(n->version, version, KS_RPCMESSAGE_VERSION_LENGTH);
- ks_hash_create(&n->method_hash,
- KS_HASH_MODE_CASE_SENSITIVE,
- KS_HASH_FLAG_RWLOCK + KS_HASH_FLAG_DUP_CHECK + KS_HASH_FLAG_FREE_VALUE,
- g_handle->pool);
- ks_hash_insert(g_handle->template_hash, n->name, n);
- }
- ks_hash_write_unlock(g_handle->template_hash);
-
- ks_log(KS_LOG_DEBUG, "Declaring application template namespace %s, version %s\n", templatename, version);
-
- return KS_STATUS_SUCCESS;
-}
-
-KS_DECLARE(ks_status_t)blade_rpc_register_template_function(char *name,
- char *command,
- jrpc_func_t func,
- jrpc_func_t respfunc)
-{
- (void)blade_rpc_find_template_locked; //remove
-
- if (!func && !respfunc) {
- return KS_STATUS_FAIL;
- }
-
- char nskey[KS_RPCMESSAGE_NAMESPACE_LENGTH];
- memset(nskey, 0, sizeof(nskey));
- strcat(nskey, name);
-
- char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
- memset(fqcommand, 0, sizeof(fqcommand));
- strcat(fqcommand, command);
-
- int lkey = strlen(fqcommand)+1;
-
- if (lkey < 16) {
- lkey = 16;
- }
-
- ks_hash_read_lock(g_handle->template_hash); /* lock template hash */
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->template_hash, nskey, KS_UNLOCKED);
-
- if (n == NULL) {
- ks_hash_read_unlock(g_handle->template_hash);
- ks_log(KS_LOG_ERROR, "Unable to find %s template\n", name);
- return KS_STATUS_FAIL;
- }
-
- ks_hash_read_lock(n->method_hash);
- blade_rpc_callbackpair_t* callbacks = ks_hash_search(n->method_hash, fqcommand, KS_UNLOCKED);
- ks_hash_read_unlock(n->method_hash);
-
- /* just ignore attempt to re register callbacks */
- /* as the template may already be in use leading to confusion */
-
- if (callbacks != NULL) {
- ks_mutex_unlock(callbacks->lock);
- ks_hash_read_unlock(g_handle->template_hash);
- ks_log(KS_LOG_ERROR, "Callbacks already registered for %s template\n", name);
- return KS_STATUS_FAIL;
- }
-
- callbacks =
- (blade_rpc_callbackpair_t*)ks_pool_alloc(g_handle->pool, lkey + sizeof(blade_rpc_callbackpair_t));
-
- strcpy(callbacks->command, command);
- callbacks->command_length = lkey;
- callbacks->request_func = func;
- callbacks->response_func = respfunc;
-
- ks_mutex_create(&callbacks->lock, KS_MUTEX_FLAG_DEFAULT, g_handle->pool);
-
- ks_hash_write_lock(n->method_hash); /* lock method hash */
-
- ks_hash_insert(n->method_hash, callbacks->command, (void *) callbacks);
-
- ks_hash_write_unlock(n->method_hash); /* unlock method hash */
- ks_hash_read_unlock(g_handle->template_hash); /* unlock namespace hash */
-
- ks_log(KS_LOG_DEBUG, "Template message %s %s registered\n", name, command);
-
- return KS_STATUS_SUCCESS;
-
-}
-
-KS_DECLARE(ks_status_t)blade_rpc_inherit_template(char *namespace, char* template)
-{
- ks_hash_read_lock(g_handle->template_hash);
-
- char tkey[KS_RPCMESSAGE_NAMESPACE_LENGTH+1];
- memset(tkey, 0, sizeof(tkey));
- strcpy(tkey, template);
-
- char nskey[KS_RPCMESSAGE_NAMESPACE_LENGTH+1];
- memset(nskey, 0, sizeof(tkey));
- strcpy(nskey, namespace);
-
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->template_hash, tkey, KS_UNLOCKED);
-
- if (!n) {
- ks_hash_read_unlock(g_handle->template_hash);
- ks_log(KS_LOG_ERROR, "Unable to locate template %s\n", template);
- return KS_STATUS_FAIL;
- }
-
- ks_hash_read_lock(g_handle->namespace_hash);
-
- blade_rpc_namespace_t *ns = ks_hash_search(g_handle->namespace_hash, nskey, KS_UNLOCKED);
-
- if (!ns) {
- ks_hash_read_unlock(g_handle->template_hash);
- ks_hash_read_unlock(g_handle->namespace_hash);
- ks_log(KS_LOG_ERROR, "Unable to locate namespace %s\n", namespace);
- return KS_STATUS_FAIL;
- }
-
- ks_hash_write_lock(ns->method_hash);
-
- ks_hash_iterator_t* it = ks_hash_first(n->method_hash, KS_HASH_FLAG_RWLOCK);
-
- while (it) {
-
- const void *key;
- void *value;
- ks_ssize_t len = strlen(key);
-
- ks_hash_this(it, &key, &len, &value);
- blade_rpc_callbackpair_t *t_callback = (blade_rpc_callbackpair_t *)value;
-
- ks_mutex_lock(t_callback->lock);
-
- int lkey = t_callback->command_length;
-
- blade_rpc_callbackpair_t *callbacks =
- (blade_rpc_callbackpair_t*)ks_pool_alloc(g_handle->pool, lkey + sizeof(blade_rpc_callbackpair_t));
-
- strcat(callbacks->command, template);
- strcat(callbacks->command, ".");
- strcat(callbacks->command, t_callback->command);
-
- callbacks->command_length = lkey;
- callbacks->request_func = t_callback->request_func;
- callbacks->response_func = t_callback->response_func;
- ks_mutex_create(&callbacks->lock, KS_MUTEX_FLAG_DEFAULT, g_handle->pool);
-
- ks_hash_insert(ns->method_hash, callbacks->command, (void *) callbacks);
-
- ks_mutex_unlock(t_callback->lock);
-
- it = ks_hash_next(&it);
- }
-
-
- ks_hash_write_lock(ns->method_hash);
-
- ks_hash_read_unlock(g_handle->namespace_hash);
- ks_hash_read_unlock(g_handle->template_hash);
-
- return KS_STATUS_SUCCESS;
-}
-
-
-/*
- * 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)
-{
- cJSON *jversion = NULL;
- blade_rpc_callbackpair_t* callbacks = NULL;
-
- *requestP = NULL;
-
- ks_hash_read_lock(g_handle->namespace_hash);
- blade_rpc_namespace_t *n = ks_hash_search(g_handle->namespace_hash, namespace, KS_UNLOCKED);
-
- if (n) {
- ks_hash_read_lock(n->method_hash);
- callbacks = ks_hash_search(n->method_hash, method, KS_UNLOCKED);
- if (callbacks) {
- jversion = cJSON_CreateString(n->version);
- }
- ks_hash_read_unlock(n->method_hash);
- }
-
- ks_hash_read_unlock(g_handle->namespace_hash);
-
- if (!n) {
- ks_log(KS_LOG_ERROR, "No namespace %s found\n", namespace);
- return 0;
- }
-
- if (!callbacks) {
- ks_log(KS_LOG_ERROR, "No method %s.%s found\n", namespace, method);
- return 0;
- }
-
- ks_rpcmessageid_t msgid = ks_rpcmessage_create_request(namespace, method, paramsP, requestP);
-
- if (!msgid || *requestP == NULL) {
- ks_log(KS_LOG_ERROR, "Unable to create rpc message for method %s.%s\n", namespace, method);
- return 0;
- }
-
- cJSON *jfields = cJSON_CreateObject();
-
- cJSON_AddItemToObject(jfields, "version", jversion);
-
- if (fields->to) {
- cJSON_AddStringToObject(jfields, "to", fields->to);
- }
-
- if (fields->from) {
- cJSON_AddStringToObject(jfields, "from", fields->from);
- }
-
- if (fields->token) {
- cJSON_AddStringToObject(jfields, "token", fields->token);
- }
-
- cJSON_AddItemToObject(*requestP, "blade", jfields);
-
- return msgid;
-}
-
-KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_response(cJSON *request,
- cJSON **replyP,
- cJSON **responseP)
-{
- cJSON *jfields = cJSON_GetObjectItem(request, "blade");
-
- if (!jfields) {
- ks_log(KS_LOG_ERROR, "No blade routing info found. Unable to create response\n");
- return 0;
- }
-
- ks_rpcmessageid_t msgid = ks_rpcmessage_create_response(request, replyP, responseP);
-
- if (!msgid || *responseP == NULL) {
- ks_log(KS_LOG_ERROR, "Unable to create rpc response message\n"); //TODO : Add namespace, method from request
- return 0;
- }
-
- const char *to = cJSON_GetObjectCstr(jfields, "to");
- const char *from = cJSON_GetObjectCstr(jfields, "from");
- const char *token = cJSON_GetObjectCstr(jfields, "token");
- const char *version = cJSON_GetObjectCstr(jfields, "version");
-
- cJSON *blade = cJSON_CreateObject();
-
- if (to) {
- cJSON_AddStringToObject(blade, "to", from);
- }
-
- if (from) {
- cJSON_AddStringToObject(blade, "from", to);
- }
-
- if (token) {
- cJSON_AddStringToObject(blade, "token", token);
- }
-
- if (version) {
- cJSON_AddStringToObject(blade, "version", version);
- }
-
- cJSON_AddItemToObject(*responseP, "blade", blade);
-
- return msgid;
-}
-
-KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_errorresponse(cJSON *request,
- cJSON **errorP,
- cJSON **responseP)
-{
- ks_rpcmessageid_t msgid = blade_rpc_create_response(request, NULL, responseP);
-
- if (msgid) {
-
- if (errorP) {
-
- if (*errorP) {
- cJSON_AddItemToObject(*responseP, "error", *errorP);
- }
- else {
- cJSON *error = cJSON_CreateObject();
- cJSON_AddItemToObject(*responseP, "error", error);
- *errorP = error;
- }
- }
- }
-
- return msgid;
-}
-
-
-const char BLADE_JRPC_METHOD[] = "method";
-const char BLADE_JRPC_ID[] = "id";
-const char BLADE_JRPC_FIELDS[] = "blade";
-const char BLADE_JRPC_TO[] = "to";
-const char BLADE_JRPC_FROM[] = "from";
-const char BLADE_JRPC_TOKEN[] = "token";
-const char BLADE_JRPC_VERSION[] = "version";
-
-KS_DECLARE(ks_status_t) blade_rpc_parse_message(cJSON *message,
- char **namespaceP,
- char **methodP,
- char **versionP,
- uint32_t *idP,
- blade_rpc_fields_t **fieldsP)
-{
- const char *m = cJSON_GetObjectCstr(message, BLADE_JRPC_METHOD);
- cJSON *blade = cJSON_GetObjectItem(message, BLADE_JRPC_FIELDS);
- cJSON *jid = cJSON_GetObjectItem(message, BLADE_JRPC_ID);
-
- *fieldsP = NULL;
- *namespaceP = NULL;
- *versionP = NULL;
- *methodP = NULL;
- *idP = 0;
-
- if (jid) {
- *idP = jid->valueint;
- }
-
- if (!m || !blade) {
- const char *buffer = cJSON_PrintUnformatted(message);
- ks_log(KS_LOG_ERROR, "Unable to locate necessary fields in message:\n%s\n", buffer);
- ks_pool_free(g_handle->pool, buffer);
- return KS_STATUS_FAIL;
- }
-
- cJSON *jto = cJSON_GetObjectItem(blade, BLADE_JRPC_TO);
- cJSON *jfrom = cJSON_GetObjectItem(blade, BLADE_JRPC_FROM);
- cJSON *jtoken = cJSON_GetObjectItem(blade, BLADE_JRPC_TOKEN);
-
-
- ks_size_t len = KS_RPCMESSAGE_COMMAND_LENGTH + 1 +
- KS_RPCMESSAGE_NAMESPACE_LENGTH + 1 +
- KS_RPCMESSAGE_VERSION_LENGTH + 1 +
- sizeof(blade_rpc_fields_t) + 1;
-
- uint32_t lento = 0;
- uint32_t lenfrom = 0;
- uint32_t lentoken = 0;
-
- if (jto) {
- lento = strlen(jto->valuestring) + 1;
- len += lento;
- }
-
- if (jfrom) {
- lenfrom += strlen(jfrom->valuestring) + 1;
- len += lenfrom;
- }
-
- if (jtoken) {
- lentoken += strlen(jtoken->valuestring) + 1;
- len += lentoken;
- }
-
- blade_rpc_fields_t *fields = (blade_rpc_fields_t *)ks_pool_alloc(g_handle->pool, len);
-
- char *namespace = (char*)fields + sizeof(blade_rpc_fields_t);
- char *command = namespace + KS_RPCMESSAGE_NAMESPACE_LENGTH + 1;
- char *version = command + KS_RPCMESSAGE_COMMAND_LENGTH + 1;
-
- char *ptr = version + KS_RPCMESSAGE_VERSION_LENGTH + 1;
-
- if (jto) {
- strcpy(ptr, jto->valuestring);
- fields->to = ptr;
- ptr += strlen(jto->valuestring) + 1;
- }
-
- if (jfrom) {
- strcpy(ptr, jfrom->valuestring);
- fields->from = ptr;
- ptr += strlen(jfrom->valuestring) + 1;
- }
-
- if (jtoken) {
- strcpy(ptr, jtoken->valuestring);
- fields->token = ptr;
- ptr += strlen(jtoken->valuestring) + 1;
- }
-
- blade_rpc_parse_fqcommand(m, namespace, command);
-
- strcpy(version, cJSON_GetObjectCstr(blade, BLADE_JRPC_VERSION));
-
- *fieldsP = fields;
- *namespaceP = namespace;
- *methodP = command;
- *versionP = version;
-
- return KS_STATUS_SUCCESS;
-}
-
-
-/*
- * send message
- * ------------
- */
-
-KS_DECLARE(ks_status_t) blade_rpc_write_data(char *sessionid, char* data, uint32_t size)
-{
-
- ks_status_t s = KS_STATUS_FAIL;
-
- // convert to json
- cJSON *msg = cJSON_Parse(data);
-
- if (msg) {
-
- // ks_status_t blade_peer_message_push(blade_peer_t *peer, void *data, int32_t data_length);
-
- s = KS_STATUS_SUCCESS;
- }
- else {
- ks_log(KS_LOG_ERROR, "Unable to format outbound message\n");
- }
-
-
- // ks_rpc_write_json
- // ks_status_t blade_peer_message_push(blade_peer_t *peer, void *data, int32_t data_length);
- return s;
-}
-
-
-KS_DECLARE(ks_status_t) blade_rpc_write_json(cJSON* json)
-{
- // just push the messages onto the communication manager
- // synchronization etc, taken care of by the transport api'
- char *data = cJSON_PrintUnformatted(json);
- if (data) {
- ks_log(KS_LOG_DEBUG, "%s\n", data);
- //return blade_rpc_write_data(sessionid, data, strlen(data));
- return KS_STATUS_SUCCESS;
- }
- ks_log(KS_LOG_ERROR, "Unable to parse json\n");
- return KS_STATUS_FAIL;
-}
-
-
-
-
-/*
- * Transport layer callbacks follow below
- *
-*/
-
-
-
-
-/*
- * rpc message processing
- */
-static ks_status_t blade_rpc_process_jsonmessage_all(cJSON *request)
-{
- const char *fqcommand = cJSON_GetObjectCstr(request, "method");
- cJSON *error = NULL;
- cJSON *response = NULL;
- cJSON *responseP = NULL;
-
- if (!fqcommand) {
- error = cJSON_CreateObject();
- cJSON_AddStringToObject(error, "errormessage", "Command not specified");
- ks_rpcmessage_create_request("rpcprotocol", "unknowncommand", &error, &responseP);
- blade_rpc_write_json(responseP);
- return KS_STATUS_FAIL;
- }
-
-
- char namespace[KS_RPCMESSAGE_NAMESPACE_LENGTH];
- char command[KS_RPCMESSAGE_COMMAND_LENGTH];
-
- blade_rpc_parse_fqcommand(fqcommand, namespace, command);
- blade_rpc_callbackpair_t* callbacks = blade_rpc_find_callbacks_locked(namespace, command);
-
- if (!callbacks) {
- error = cJSON_CreateObject();
- cJSON_AddStringToObject(error, "errormessage", "Command not supported");
- ks_rpcmessage_create_response(request, &error, &responseP);
- blade_rpc_write_json(responseP);
- return KS_STATUS_FAIL;
- }
-
- //todo - add more checks ?
-
- ks_bool_t isrequest = ks_rpcmessage_isrequest(request);
-
- enum jrpc_status_t jrcs = 0;
-
- if (isrequest && callbacks->request_func) {
-
- cJSON *responseP = NULL;
-
- if (callbacks->custom && callbacks->custom->prefix_request_func) {
- jrcs = callbacks->custom->prefix_request_func(request, &responseP);
- if ( (jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- if ( !(jrcs & JRPC_EXIT) && jrcs != JRPC_ERROR) {
- jrcs = callbacks->request_func(request, &responseP);
- if ((jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- if ( !(jrcs & JRPC_EXIT) && jrcs != JRPC_ERROR && callbacks->custom && callbacks->custom->postfix_request_func) {
- jrcs = callbacks->custom->postfix_request_func(request, &responseP);
- if ( (jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- ks_mutex_unlock(callbacks->lock);
-
- if (jrcs == JRPC_ERROR) {
- return KS_STATUS_FAIL;
- }
-
- return KS_STATUS_SUCCESS;
- }
- else if (!isrequest && callbacks->response_func) {
-
- if (callbacks->custom && callbacks->custom->prefix_response_func) {
- jrcs = callbacks->custom->prefix_response_func(response, &responseP);
- if ( (jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- if ( !(jrcs & JRPC_EXIT) && jrcs != JRPC_ERROR) {
- jrcs = callbacks->response_func(response, &responseP);
- if ( (jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- if ( !(jrcs & JRPC_EXIT) && jrcs != JRPC_ERROR && callbacks->custom && callbacks->custom->postfix_response_func) {
- jrcs = callbacks->custom->postfix_response_func(response, &responseP);
- if ( (jrcs & JRPC_SEND) && responseP) {
- blade_rpc_write_json(responseP);
- cJSON_Delete(responseP);
- responseP = NULL;
- }
- }
-
- ks_mutex_unlock(callbacks->lock);
-
- if (jrcs == JRPC_ERROR) {
- return KS_STATUS_FAIL;
- }
-
- return KS_STATUS_SUCCESS;
- }
-
- ks_log(KS_LOG_ERROR, "Unable to find message handler for %s\n", command);
-
- return KS_STATUS_FAIL;
-}
-
-/*
- *
-*/
-KS_DECLARE(ks_status_t) blade_rpc_process_jsonmessage(cJSON *request)
-{
- ks_status_t respstatus = blade_rpc_process_jsonmessage_all(request);
- return respstatus;
-}
-
-KS_DECLARE(ks_status_t) blade_rpc_process_data(const uint8_t *data,
- ks_size_t size)
-{
-
- cJSON *json = cJSON_Parse((const char*)data);
- if (json != NULL) {
- ks_log( KS_LOG_ERROR, "Unable to parse message\n");
- return KS_STATUS_FAIL;
- }
-
- /* deal with rpc message */
- if (ks_rpcmessage_isrpc(json)) {
- ks_status_t respstatus = blade_rpc_process_jsonmessage_all(json);
- return respstatus;
- }
-
- ks_log(KS_LOG_ERROR, "Unable to identify message type\n");
-
- return KS_STATUS_FAIL;
-}
-
-//KS_DECLARE(ks_status_t) blade_rpc_process_blademessage(blade_message_t *message)
-//{
-// uint8_t* data = NULL;
-// ks_size_t size = 0;
-//
-// blade_message_get(message, (void **)&data, &size);
-//
-// if (data && size>0) {
-// ks_status_t s = blade_rpc_process_data(data, size);
-// blade_message_discard(&message);
-// return s;
-// }
-//
-// ks_log(KS_LOG_ERROR, "Message read failed\n");
-// return KS_STATUS_FAIL;
-//
-//}
-
-
-/* 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:
- */
-
ks_assert(bs);
ks_log(KS_LOG_DEBUG, "Session (%s) state destroy\n", bs->id);
+
blade_handle_sessions_remove(bs);
blade_session_destroy(&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)) {
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")) {
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, '.');
+
+ 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);
- blade_request_create(&breq, bs->handle, bs->id, json);
+ 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?
}
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:
--- /dev/null
+/*
+ * 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:
+ */
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;
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,
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);
*bhP = bh;
+ ks_log(KS_LOG_DEBUG, "Created\n");
+
return KS_STATUS_SUCCESS;
}
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)) {
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
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;
+++ /dev/null
-/*
- * 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:
- */
/*
* 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
#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
/*
- * 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
* 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
#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
+++ /dev/null
-/*
- * 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
-
/*
* 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
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);
/*
- * 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
* 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:
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);
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;
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
};
-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)
+++ /dev/null
-#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, ¶ms1, &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, ¶ms1, &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, ¶ms1, &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;
-}
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
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
-
-
-
-
/*
* 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
#include "ks_bencode.h"
#include "ks_rng.h"
#include "ks_acl.h"
-#include "ks_rpcmessage.h"
#include "ks_base64.h"
KS_END_EXTERN_C
+++ /dev/null
-/*
- * 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:
- */
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)
#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)
$(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
-
+++ /dev/null
-#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;
-}