mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-17 09:12:25 +00:00
FS-9952: Big commit, first registered jsonrpc echo call successful, lots of cleanup remaining
This commit is contained in:
parent
fd49aebb1d
commit
8f569f715b
@ -11,23 +11,20 @@ libunqlite_la_CFLAGS = -DUNQLITE_ENABLE_THREADS
|
|||||||
libunqlite_la_LIBADD = -lpthread
|
libunqlite_la_LIBADD = -lpthread
|
||||||
|
|
||||||
lib_LTLIBRARIES = libblade.la
|
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.c src/blade_stack.c
|
||||||
libblade_la_SOURCES += src/blade_rpcproto.c
|
libblade_la_SOURCES += src/blade_datastore.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_identity.c src/blade_module.c src/blade_connection.c
|
||||||
libblade_la_SOURCES += src/blade_session.c src/blade_protocol.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_CFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
|
||||||
libblade_la_LDFLAGS = -version-info 0:1:0 -lncurses -lpthread -lm -lconfig $(AM_LDFLAGS)
|
libblade_la_LDFLAGS = -version-info 0:1:0 -lncurses -lpthread -lm -lconfig $(AM_LDFLAGS)
|
||||||
libblade_la_LIBADD = libunqlite.la
|
libblade_la_LIBADD = libunqlite.la
|
||||||
library_includedir = $(prefix)/include
|
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/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_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_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_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
|
library_include_HEADERS += src/include/unqlite.h test/tap.h
|
||||||
|
|
||||||
tests: libblade.la
|
tests: libblade.la
|
||||||
$(MAKE) -C test tests
|
$(MAKE) -C test tests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -495,6 +495,7 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc)
|
|||||||
blade_transport_state_callback_t callback = NULL;
|
blade_transport_state_callback_t callback = NULL;
|
||||||
blade_connection_state_hook_t hook = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
blade_connection_state_hook_t hook = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
||||||
cJSON *json = NULL;
|
cJSON *json = NULL;
|
||||||
|
blade_session_t *bs = NULL;
|
||||||
ks_bool_t done = KS_FALSE;
|
ks_bool_t done = KS_FALSE;
|
||||||
|
|
||||||
ks_assert(bc);
|
ks_assert(bc);
|
||||||
@ -514,14 +515,18 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc)
|
|||||||
blade_connection_disconnect(bc);
|
blade_connection_disconnect(bc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(done = (json == NULL))) {
|
if (!(done = (json == NULL))) {
|
||||||
blade_session_t *bs = blade_handle_sessions_get(bc->handle, bc->session);
|
if (!bs) {
|
||||||
|
bs = blade_handle_sessions_get(bc->handle, bc->session);
|
||||||
ks_assert(bs);
|
ks_assert(bs);
|
||||||
|
}
|
||||||
blade_session_receiving_push(bs, json);
|
blade_session_receiving_push(bs, json);
|
||||||
cJSON_Delete(json);
|
cJSON_Delete(json);
|
||||||
json = NULL;
|
json = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (bs) blade_session_read_unlock(bs);
|
||||||
|
|
||||||
callback = blade_connection_state_callback_lookup(bc, BLADE_CONNECTION_STATE_READY);
|
callback = blade_connection_state_callback_lookup(bc, BLADE_CONNECTION_STATE_READY);
|
||||||
if (callback) hook = callback(bc, BLADE_CONNECTION_STATE_CONDITION_POST);
|
if (callback) hook = callback(bc, BLADE_CONNECTION_STATE_CONDITION_POST);
|
||||||
|
118
libs/libblade/src/blade_method.c
Normal file
118
libs/libblade/src/blade_method.c
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Shane Bryldt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blade.h"
|
||||||
|
|
||||||
|
struct blade_method_s {
|
||||||
|
blade_handle_t *handle;
|
||||||
|
ks_pool_t *pool;
|
||||||
|
|
||||||
|
blade_space_t *space;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
blade_request_callback_t callback;
|
||||||
|
// @todo more fun descriptive information about the call for remote registrations
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_method_create(blade_method_t **bmP, blade_space_t *bs, const char *name, blade_request_callback_t callback)
|
||||||
|
{
|
||||||
|
blade_handle_t *bh = NULL;
|
||||||
|
blade_method_t *bm = NULL;
|
||||||
|
ks_pool_t *pool = NULL;
|
||||||
|
|
||||||
|
ks_assert(bmP);
|
||||||
|
ks_assert(bs);
|
||||||
|
ks_assert(name);
|
||||||
|
|
||||||
|
bh = blade_space_handle_get(bs);
|
||||||
|
ks_assert(bh);
|
||||||
|
|
||||||
|
pool = blade_handle_pool_get(bh);
|
||||||
|
ks_assert(pool);
|
||||||
|
|
||||||
|
bm = ks_pool_alloc(pool, sizeof(blade_method_t));
|
||||||
|
bm->handle = bh;
|
||||||
|
bm->pool = pool;
|
||||||
|
bm->space = bs;
|
||||||
|
bm->name = name; // @todo dup and keep copy? should mostly be literals
|
||||||
|
bm->callback = callback;
|
||||||
|
|
||||||
|
*bmP = bm;
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "Method Created: %s.%s\n", blade_space_path_get(bs), name);
|
||||||
|
|
||||||
|
return KS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_method_destroy(blade_method_t **bmP)
|
||||||
|
{
|
||||||
|
blade_method_t *bm = NULL;
|
||||||
|
|
||||||
|
ks_assert(bmP);
|
||||||
|
ks_assert(*bmP);
|
||||||
|
|
||||||
|
bm = *bmP;
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "Method Destroyed: %s.%s\n", blade_space_path_get(bm->space), bm->name);
|
||||||
|
|
||||||
|
ks_pool_free(bm->pool, bmP);
|
||||||
|
|
||||||
|
return KS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(const char *) blade_method_name_get(blade_method_t *bm)
|
||||||
|
{
|
||||||
|
ks_assert(bm);
|
||||||
|
|
||||||
|
return bm->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(blade_request_callback_t) blade_method_callback_get(blade_method_t *bm)
|
||||||
|
{
|
||||||
|
ks_assert(bm);
|
||||||
|
|
||||||
|
return bm->callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* For Emacs:
|
||||||
|
* Local Variables:
|
||||||
|
* mode:c
|
||||||
|
* indent-tabs-mode:t
|
||||||
|
* tab-width:4
|
||||||
|
* c-basic-offset:4
|
||||||
|
* End:
|
||||||
|
* For VIM:
|
||||||
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||||
|
*/
|
@ -111,8 +111,10 @@ blade_connection_state_hook_t blade_transport_wss_on_state_connect_inbound(blade
|
|||||||
blade_connection_state_hook_t blade_transport_wss_on_state_connect_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
|
blade_connection_state_hook_t blade_transport_wss_on_state_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_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_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_detach_inbound(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_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
|
||||||
|
blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
|
||||||
|
blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -120,6 +122,9 @@ ks_status_t blade_transport_wss_init_create(blade_transport_wss_init_t **bt_wssi
|
|||||||
ks_status_t blade_transport_wss_init_destroy(blade_transport_wss_init_t **bt_wssiP);
|
ks_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 =
|
static blade_module_callbacks_t g_module_wss_callbacks =
|
||||||
{
|
{
|
||||||
@ -144,10 +149,10 @@ static blade_transport_callbacks_t g_transport_wss_callbacks =
|
|||||||
blade_transport_wss_on_state_connect_outbound,
|
blade_transport_wss_on_state_connect_outbound,
|
||||||
blade_transport_wss_on_state_attach_inbound,
|
blade_transport_wss_on_state_attach_inbound,
|
||||||
blade_transport_wss_on_state_attach_outbound,
|
blade_transport_wss_on_state_attach_outbound,
|
||||||
blade_transport_wss_on_state_detach,
|
blade_transport_wss_on_state_detach_inbound,
|
||||||
blade_transport_wss_on_state_detach,
|
blade_transport_wss_on_state_detach_outbound,
|
||||||
blade_transport_wss_on_state_ready,
|
blade_transport_wss_on_state_ready_inbound,
|
||||||
blade_transport_wss_on_state_ready,
|
blade_transport_wss_on_state_ready_outbound,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -385,6 +390,8 @@ ks_status_t blade_module_wss_config(blade_module_wss_t *bm_wss, config_setting_t
|
|||||||
KS_DECLARE(ks_status_t) blade_module_wss_on_startup(blade_module_t *bm, config_setting_t *config)
|
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_module_wss_t *bm_wss = NULL;
|
||||||
|
blade_space_t *space = NULL;
|
||||||
|
blade_method_t *method = NULL;
|
||||||
|
|
||||||
ks_assert(bm);
|
ks_assert(bm);
|
||||||
ks_assert(config);
|
ks_assert(config);
|
||||||
@ -419,6 +426,17 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_startup(blade_module_t *bm, config_s
|
|||||||
|
|
||||||
blade_handle_transport_register(bm_wss->handle, bm, BLADE_MODULE_WSS_TRANSPORT_NAME, bm_wss->transport_callbacks);
|
blade_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");
|
ks_log(KS_LOG_DEBUG, "Started\n");
|
||||||
|
|
||||||
return KS_STATUS_SUCCESS;
|
return KS_STATUS_SUCCESS;
|
||||||
@ -428,6 +446,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
|
|||||||
{
|
{
|
||||||
blade_module_wss_t *bm_wss = NULL;
|
blade_module_wss_t *bm_wss = NULL;
|
||||||
blade_connection_t *bc = NULL;
|
blade_connection_t *bc = NULL;
|
||||||
|
ks_bool_t stopped = KS_FALSE;
|
||||||
|
|
||||||
ks_assert(bm);
|
ks_assert(bm);
|
||||||
|
|
||||||
@ -440,6 +459,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
|
|||||||
ks_thread_join(bm_wss->listeners_thread);
|
ks_thread_join(bm_wss->listeners_thread);
|
||||||
ks_pool_free(bm_wss->pool, &bm_wss->listeners_thread);
|
ks_pool_free(bm_wss->pool, &bm_wss->listeners_thread);
|
||||||
bm_wss->shutdown = KS_FALSE;
|
bm_wss->shutdown = KS_FALSE;
|
||||||
|
stopped = KS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
|
for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
|
||||||
@ -461,7 +481,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm)
|
|||||||
while (list_size(&bm_wss->connected) > 0) ks_sleep_ms(100);
|
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;
|
return KS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -751,7 +771,6 @@ ks_status_t blade_transport_wss_write(blade_transport_wss_t *bt_wss, cJSON *json
|
|||||||
|
|
||||||
ks_status_t blade_transport_wss_on_send(blade_connection_t *bc, cJSON *json)
|
ks_status_t 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;
|
blade_transport_wss_t *bt_wss = NULL;
|
||||||
|
|
||||||
ks_assert(bc);
|
ks_assert(bc);
|
||||||
@ -759,11 +778,7 @@ ks_status_t blade_transport_wss_on_send(blade_connection_t *bc, cJSON *json)
|
|||||||
|
|
||||||
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
|
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
|
||||||
|
|
||||||
ret = blade_transport_wss_write(bt_wss, json);
|
return blade_transport_wss_write(bt_wss, json);
|
||||||
|
|
||||||
cJSON_Delete(json);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ks_status_t blade_transport_wss_read(blade_transport_wss_t *bt_wss, cJSON **json)
|
ks_status_t blade_transport_wss_read(blade_transport_wss_t *bt_wss, cJSON **json)
|
||||||
@ -814,6 +829,29 @@ ks_status_t blade_transport_wss_on_receive(blade_connection_t *bc, cJSON **json)
|
|||||||
return blade_transport_wss_read(bt_wss, json);
|
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_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_transport_wss_t *bt_wss = NULL;
|
||||||
@ -924,10 +962,11 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
{
|
{
|
||||||
blade_connection_state_hook_t ret = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
blade_connection_state_hook_t ret = BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
||||||
blade_transport_wss_t *bt_wss = NULL;
|
blade_transport_wss_t *bt_wss = NULL;
|
||||||
|
ks_pool_t *pool = NULL;
|
||||||
cJSON *json_req = NULL;
|
cJSON *json_req = NULL;
|
||||||
cJSON *json_res = NULL;
|
cJSON *json_res = NULL;
|
||||||
cJSON *params = NULL;
|
cJSON *json_params = NULL;
|
||||||
cJSON *result = NULL;
|
cJSON *json_result = NULL;
|
||||||
//cJSON *error = NULL;
|
//cJSON *error = NULL;
|
||||||
blade_session_t *bs = NULL;
|
blade_session_t *bs = NULL;
|
||||||
blade_handle_t *bh = NULL;
|
blade_handle_t *bh = NULL;
|
||||||
@ -948,6 +987,8 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
|
|
||||||
bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
|
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
|
// @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);
|
timeout = ks_time_now() + (5 * KS_USEC_PER_SEC);
|
||||||
while (blade_transport_wss_read(bt_wss, &json_req) == KS_STATUS_SUCCESS) {
|
while (blade_transport_wss_read(bt_wss, &json_req) == KS_STATUS_SUCCESS) {
|
||||||
@ -958,6 +999,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
|
|
||||||
if (!json_req) {
|
if (!json_req) {
|
||||||
ks_log(KS_LOG_DEBUG, "Failed to receive message before timeout\n");
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -966,7 +1008,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
jsonrpc = cJSON_GetObjectCstr(json_req, "jsonrpc"); // @todo check for definitions of these keys and fixed values
|
jsonrpc = cJSON_GetObjectCstr(json_req, "jsonrpc"); // @todo check for definitions of these keys and fixed values
|
||||||
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
|
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
|
||||||
ks_log(KS_LOG_DEBUG, "Received message is not the expected protocol\n");
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -974,7 +1016,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
id = cJSON_GetObjectCstr(json_req, "id"); // @todo switch to number if we are not using a uuid for message id
|
id = cJSON_GetObjectCstr(json_req, "id"); // @todo switch to number if we are not using a uuid for message id
|
||||||
if (!id) {
|
if (!id) {
|
||||||
ks_log(KS_LOG_DEBUG, "Received message is missing 'id'\n");
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -982,14 +1024,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
method = cJSON_GetObjectCstr(json_req, "method");
|
method = cJSON_GetObjectCstr(json_req, "method");
|
||||||
if (!method || strcasecmp(method, "blade.session.attach")) {
|
if (!method || strcasecmp(method, "blade.session.attach")) {
|
||||||
ks_log(KS_LOG_DEBUG, "Received message is missing 'method' or is an unexpected method\n");
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
params = cJSON_GetObjectItem(json_req, "params");
|
json_params = cJSON_GetObjectItem(json_req, "params");
|
||||||
if (params) {
|
if (json_params) {
|
||||||
sid = cJSON_GetObjectCstr(params, "session-id");
|
sid = cJSON_GetObjectCstr(json_params, "session-id");
|
||||||
if (sid) {
|
if (sid) {
|
||||||
// @todo validate uuid format by parsing, not currently available in uuid functions, send -32602 (invalid params) if invalid
|
// @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);
|
ks_log(KS_LOG_DEBUG, "Session (%s) requested\n", sid);
|
||||||
@ -1019,7 +1061,7 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
|
|
||||||
if (blade_session_startup(bs) != KS_STATUS_SUCCESS) {
|
if (blade_session_startup(bs) != KS_STATUS_SUCCESS) {
|
||||||
ks_log(KS_LOG_DEBUG, "Session (%s) startup failed\n", blade_session_id_get(bs));
|
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_read_unlock(bs);
|
||||||
blade_session_destroy(&bs);
|
blade_session_destroy(&bs);
|
||||||
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
@ -1030,17 +1072,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_inbound(blade_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @todo wrapper to generate request and response
|
// @todo wrapper to generate request and response
|
||||||
json_res = cJSON_CreateObject();
|
blade_rpc_response_create(pool, &json_res, &json_result, id);
|
||||||
cJSON_AddStringToObject(json_res, "jsonrpc", "2.0");
|
ks_assert(json_res);
|
||||||
cJSON_AddStringToObject(json_res, "id", id);
|
|
||||||
|
|
||||||
result = cJSON_CreateObject();
|
cJSON_AddStringToObject(json_result, "session-id", blade_session_id_get(bs));
|
||||||
cJSON_AddStringToObject(result, "session-id", blade_session_id_get(bs));
|
|
||||||
cJSON_AddItemToObject(json_res, "result", result);
|
|
||||||
|
|
||||||
// @todo send response
|
// @todo send response
|
||||||
if (blade_transport_wss_write(bt_wss, json_res) != KS_STATUS_SUCCESS) {
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1064,14 +1103,14 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
|
|||||||
blade_transport_wss_init_t *bt_wss_init = NULL;
|
blade_transport_wss_init_t *bt_wss_init = NULL;
|
||||||
ks_pool_t *pool = NULL;
|
ks_pool_t *pool = NULL;
|
||||||
cJSON *json_req = NULL;
|
cJSON *json_req = NULL;
|
||||||
|
cJSON *json_params = NULL;
|
||||||
cJSON *json_res = NULL;
|
cJSON *json_res = NULL;
|
||||||
uuid_t msgid;
|
|
||||||
const char *mid = NULL;
|
const char *mid = NULL;
|
||||||
ks_time_t timeout;
|
ks_time_t timeout;
|
||||||
const char *jsonrpc = NULL;
|
const char *jsonrpc = NULL;
|
||||||
const char *id = NULL;
|
const char *id = NULL;
|
||||||
cJSON *error = NULL;
|
cJSON *json_error = NULL;
|
||||||
cJSON *result = NULL;
|
cJSON *json_result = NULL;
|
||||||
const char *sid = NULL;
|
const char *sid = NULL;
|
||||||
blade_session_t *bs = NULL;
|
blade_session_t *bs = NULL;
|
||||||
|
|
||||||
@ -1087,25 +1126,15 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
|
|||||||
pool = blade_connection_pool_get(bc);
|
pool = blade_connection_pool_get(bc);
|
||||||
|
|
||||||
|
|
||||||
// @todo wrapper to build a request and response/error
|
blade_rpc_request_create(pool, &json_req, &json_params, &mid, "blade.session.attach");
|
||||||
json_req = cJSON_CreateObject();
|
ks_assert(json_req);
|
||||||
cJSON_AddStringToObject(json_req, "jsonrpc", "2.0");
|
|
||||||
cJSON_AddStringToObject(json_req, "method", "blade.session.attach");
|
|
||||||
|
|
||||||
ks_uuid(&msgid);
|
if (bt_wss_init->session_id) cJSON_AddStringToObject(json_params, "session-id", bt_wss_init->session_id);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ks_log(KS_LOG_DEBUG, "Session (%s) requested\n", (bt_wss_init->session_id ? bt_wss_init->session_id : "none"));
|
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) {
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1134,26 +1163,26 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
|
|||||||
|
|
||||||
id = cJSON_GetObjectCstr(json_res, "id"); // @todo switch to number if we are not using a uuid for message id
|
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)) {
|
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;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = cJSON_GetObjectItem(json_res, "error");
|
json_error = cJSON_GetObjectItem(json_res, "error");
|
||||||
if (error) {
|
if (json_error) {
|
||||||
ks_log(KS_LOG_DEBUG, "Error message ... add the details\n");
|
ks_log(KS_LOG_DEBUG, "Error message ... add the details\n");
|
||||||
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = cJSON_GetObjectItem(json_res, "result");
|
json_result = cJSON_GetObjectItem(json_res, "result");
|
||||||
if (!result) {
|
if (!json_result) {
|
||||||
ks_log(KS_LOG_DEBUG, "Received message is missing 'result'\n");
|
ks_log(KS_LOG_DEBUG, "Received message is missing 'result'\n");
|
||||||
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
sid = cJSON_GetObjectCstr(result, "session-id");
|
sid = cJSON_GetObjectCstr(json_result, "session-id");
|
||||||
if (!sid) {
|
if (!sid) {
|
||||||
ks_log(KS_LOG_DEBUG, "Received message 'result' is missing 'session-id'\n");
|
ks_log(KS_LOG_DEBUG, "Received message 'result' is missing 'session-id'\n");
|
||||||
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
ret = BLADE_CONNECTION_STATE_HOOK_DISCONNECT;
|
||||||
@ -1192,13 +1221,12 @@ blade_connection_state_hook_t blade_transport_wss_on_state_attach_outbound(blade
|
|||||||
blade_connection_session_set(bc, blade_session_id_get(bs));
|
blade_connection_session_set(bc, blade_session_id_get(bs));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (mid) ks_pool_free(pool, &mid);
|
|
||||||
if (json_req) cJSON_Delete(json_req);
|
if (json_req) cJSON_Delete(json_req);
|
||||||
if (json_res) cJSON_Delete(json_res);
|
if (json_res) cJSON_Delete(json_res);
|
||||||
return ret;
|
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_assert(bc);
|
||||||
|
|
||||||
@ -1207,7 +1235,16 @@ blade_connection_state_hook_t blade_transport_wss_on_state_detach(blade_connecti
|
|||||||
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
blade_connection_state_hook_t blade_transport_wss_on_state_ready(blade_connection_t *bc, blade_connection_state_condition_t condition)
|
blade_connection_state_hook_t blade_transport_wss_on_state_detach_outbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
|
||||||
|
{
|
||||||
|
ks_assert(bc);
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
|
||||||
|
|
||||||
|
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_connection_t *bc, blade_connection_state_condition_t condition)
|
||||||
{
|
{
|
||||||
ks_assert(bc);
|
ks_assert(bc);
|
||||||
|
|
||||||
@ -1217,6 +1254,60 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready(blade_connectio
|
|||||||
return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
|
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:
|
/* For Emacs:
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* mode:c
|
* mode:c
|
||||||
|
@ -33,7 +33,11 @@
|
|||||||
|
|
||||||
#include "blade.h"
|
#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;
|
blade_request_t *breq = NULL;
|
||||||
ks_pool_t *pool = NULL;
|
ks_pool_t *pool = NULL;
|
||||||
@ -50,8 +54,9 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, blade_hand
|
|||||||
breq->handle = bh;
|
breq->handle = bh;
|
||||||
breq->pool = pool;
|
breq->pool = pool;
|
||||||
breq->session_id = ks_pstrdup(pool, session_id);
|
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->message_id = cJSON_GetObjectCstr(json, "id");
|
||||||
|
breq->callback = callback;
|
||||||
|
|
||||||
*breqP = breq;
|
*breqP = breq;
|
||||||
|
|
||||||
@ -95,7 +100,7 @@ KS_DECLARE(ks_status_t) blade_response_create(blade_response_t **bresP, blade_ha
|
|||||||
bres->pool = pool;
|
bres->pool = pool;
|
||||||
bres->session_id = ks_pstrdup(pool, session_id);
|
bres->session_id = ks_pstrdup(pool, session_id);
|
||||||
bres->request = breq;
|
bres->request = breq;
|
||||||
bres->message = json;
|
bres->message = cJSON_Duplicate(json, 1);
|
||||||
|
|
||||||
*bresP = bres;
|
*bresP = bres;
|
||||||
|
|
||||||
@ -120,6 +125,88 @@ KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP)
|
|||||||
return KS_STATUS_SUCCESS;
|
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:
|
/* For Emacs:
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -430,6 +430,7 @@ ks_status_t blade_session_state_on_destroy(blade_session_t *bs)
|
|||||||
ks_assert(bs);
|
ks_assert(bs);
|
||||||
|
|
||||||
ks_log(KS_LOG_DEBUG, "Session (%s) state destroy\n", bs->id);
|
ks_log(KS_LOG_DEBUG, "Session (%s) state destroy\n", bs->id);
|
||||||
|
|
||||||
blade_handle_sessions_remove(bs);
|
blade_handle_sessions_remove(bs);
|
||||||
blade_session_destroy(&bs);
|
blade_session_destroy(&bs);
|
||||||
|
|
||||||
@ -483,21 +484,31 @@ ks_status_t blade_session_state_on_ready(blade_session_t *bs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json)
|
KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json, blade_response_callback_t callback)
|
||||||
{
|
{
|
||||||
blade_request_t *request = NULL;
|
blade_request_t *request = NULL;
|
||||||
const char *method = NULL;
|
const char *method = NULL;
|
||||||
|
const char *id = NULL;
|
||||||
|
|
||||||
ks_assert(bs);
|
ks_assert(bs);
|
||||||
ks_assert(json);
|
ks_assert(json);
|
||||||
|
|
||||||
method = cJSON_GetObjectCstr(json, "method");
|
method = cJSON_GetObjectCstr(json, "method");
|
||||||
|
id = cJSON_GetObjectCstr(json, "id");
|
||||||
if (method) {
|
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);
|
ks_assert(request);
|
||||||
|
|
||||||
// @todo set request TTL and figure out when requests are checked for expiration (separate thread in the handle?)
|
// @todo set request TTL and figure out when requests are checked for expiration (separate thread in the handle?)
|
||||||
blade_handle_requests_add(request);
|
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)) {
|
if (list_empty(&bs->connections)) {
|
||||||
@ -516,20 +527,18 @@ KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json)
|
|||||||
|
|
||||||
ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
|
ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
|
||||||
{
|
{
|
||||||
ks_status_t ret = KS_STATUS_SUCCESS;
|
|
||||||
blade_request_t *breq = NULL;
|
blade_request_t *breq = NULL;
|
||||||
blade_response_t *bres = NULL;
|
blade_response_t *bres = NULL;
|
||||||
const char *jsonrpc = NULL;
|
const char *jsonrpc = NULL;
|
||||||
const char *id = NULL;
|
const char *id = NULL;
|
||||||
const char *method = NULL;
|
const char *method = NULL;
|
||||||
|
ks_bool_t disconnect = KS_FALSE;
|
||||||
|
|
||||||
ks_assert(bs);
|
ks_assert(bs);
|
||||||
ks_assert(json);
|
ks_assert(json);
|
||||||
|
|
||||||
ks_log(KS_LOG_DEBUG, "Session (%s) processing\n", bs->id);
|
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");
|
jsonrpc = cJSON_GetObjectCstr(json, "jsonrpc");
|
||||||
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
|
if (!jsonrpc || strcmp(jsonrpc, "2.0")) {
|
||||||
@ -549,13 +558,50 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
|
|||||||
|
|
||||||
method = cJSON_GetObjectCstr(json, "method");
|
method = cJSON_GetObjectCstr(json, "method");
|
||||||
if (method) {
|
if (method) {
|
||||||
// @todo use method to find RPC callbacks
|
// @note This is scenario 2
|
||||||
|
// 2) Receiving a request (server: method callee or provider)
|
||||||
|
blade_space_t *tmp_space = NULL;
|
||||||
|
blade_method_t *tmp_method = NULL;
|
||||||
|
blade_request_callback_t callback = NULL;
|
||||||
|
char *space_name = ks_pstrdup(bs->pool, method);
|
||||||
|
char *method_name = strrchr(space_name, '.');
|
||||||
|
|
||||||
blade_request_create(&breq, bs->handle, bs->id, json);
|
ks_log(KS_LOG_DEBUG, "Session (%s) receiving request (%s) for %s\n", bs->id, id, method);
|
||||||
|
|
||||||
|
if (!method_name || method_name == space_name) {
|
||||||
|
ks_pool_free(bs->pool, (void **)&space_name);
|
||||||
|
// @todo send error response, code = -32601 (method not found)
|
||||||
|
// @todo hangup session entirely?
|
||||||
|
return KS_STATUS_FAIL;
|
||||||
|
}
|
||||||
|
*method_name = '\0';
|
||||||
|
method_name++; // @todo check if can be postfixed safely on previous assignment, can't recall
|
||||||
|
|
||||||
|
tmp_space = blade_handle_space_lookup(bs->handle, space_name);
|
||||||
|
if (tmp_space) tmp_method = blade_space_methods_get(tmp_space, method_name);
|
||||||
|
|
||||||
|
ks_pool_free(bs->pool, (void **)&space_name);
|
||||||
|
|
||||||
|
if (!tmp_method) {
|
||||||
|
// @todo send error response, code = -32601 (method not found)
|
||||||
|
// @todo hangup session entirely?
|
||||||
|
return KS_STATUS_FAIL;
|
||||||
|
}
|
||||||
|
callback = blade_method_callback_get(tmp_method);
|
||||||
|
ks_assert(callback);
|
||||||
|
|
||||||
|
blade_request_create(&breq, bs->handle, bs->id, json, NULL);
|
||||||
ks_assert(breq);
|
ks_assert(breq);
|
||||||
|
|
||||||
// @todo call request callback handler
|
disconnect = callback(breq);
|
||||||
|
|
||||||
|
blade_request_destroy(&breq);
|
||||||
} else {
|
} 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);
|
breq = blade_handle_requests_get(bs->handle, id);
|
||||||
if (!breq) {
|
if (!breq) {
|
||||||
// @todo hangup session entirely?
|
// @todo hangup session entirely?
|
||||||
@ -563,18 +609,20 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json)
|
|||||||
}
|
}
|
||||||
blade_handle_requests_remove(breq);
|
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);
|
blade_response_create(&bres, bs->handle, bs->id, breq, json);
|
||||||
ks_assert(bres);
|
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:
|
/* For Emacs:
|
||||||
|
176
libs/libblade/src/blade_space.c
Normal file
176
libs/libblade/src/blade_space.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Shane Bryldt
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of the original author; nor the names of any contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blade.h"
|
||||||
|
|
||||||
|
struct blade_space_s {
|
||||||
|
blade_handle_t *handle;
|
||||||
|
ks_pool_t *pool;
|
||||||
|
|
||||||
|
const char *path;
|
||||||
|
ks_hash_t *methods;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, const char *path)
|
||||||
|
{
|
||||||
|
blade_space_t *bs = NULL;
|
||||||
|
ks_pool_t *pool = NULL;
|
||||||
|
|
||||||
|
ks_assert(bsP);
|
||||||
|
ks_assert(bh);
|
||||||
|
ks_assert(path);
|
||||||
|
|
||||||
|
pool = blade_handle_pool_get(bh);
|
||||||
|
|
||||||
|
bs = ks_pool_alloc(pool, sizeof(blade_space_t));
|
||||||
|
bs->handle = bh;
|
||||||
|
bs->pool = pool;
|
||||||
|
bs->path = path; // @todo dup and keep copy? should mostly be literals
|
||||||
|
ks_hash_create(&bs->methods, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bs->pool);
|
||||||
|
ks_assert(bs);
|
||||||
|
|
||||||
|
*bsP = bs;
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "Space Created: %s\n", path);
|
||||||
|
|
||||||
|
return KS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP)
|
||||||
|
{
|
||||||
|
blade_space_t *bs = NULL;
|
||||||
|
ks_hash_iterator_t *it = NULL;
|
||||||
|
|
||||||
|
ks_assert(bsP);
|
||||||
|
ks_assert(*bsP);
|
||||||
|
|
||||||
|
bs = *bsP;
|
||||||
|
|
||||||
|
for (it = ks_hash_first(bs->methods, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
|
||||||
|
void *key = NULL;
|
||||||
|
blade_method_t *value = NULL;
|
||||||
|
|
||||||
|
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
|
||||||
|
blade_method_destroy(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ks_hash_destroy(&bs->methods);
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "Space Destroyed: %s\n", bs->path);
|
||||||
|
|
||||||
|
ks_pool_free(bs->pool, bsP);
|
||||||
|
|
||||||
|
return KS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs)
|
||||||
|
{
|
||||||
|
ks_assert(bs);
|
||||||
|
|
||||||
|
return bs->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs)
|
||||||
|
{
|
||||||
|
ks_assert(bs);
|
||||||
|
|
||||||
|
return bs->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_space_methods_add(blade_space_t *bs, blade_method_t *bm)
|
||||||
|
{
|
||||||
|
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||||
|
const char *name = NULL;
|
||||||
|
blade_method_t *bm_old = NULL;
|
||||||
|
|
||||||
|
ks_assert(bs);
|
||||||
|
ks_assert(bm);
|
||||||
|
|
||||||
|
name = blade_method_name_get(bm);
|
||||||
|
ks_assert(name);
|
||||||
|
|
||||||
|
ks_hash_write_lock(bs->methods);
|
||||||
|
bm_old = ks_hash_search(bs->methods, (void *)name, KS_UNLOCKED);
|
||||||
|
if (bm_old) ks_hash_remove(bs->methods, (void *)name);
|
||||||
|
ret = ks_hash_insert(bs->methods, (void *)name, (void *)bm);
|
||||||
|
ks_hash_write_unlock(bs->methods);
|
||||||
|
|
||||||
|
if (bm_old) blade_method_destroy(&bm_old);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(ks_status_t) blade_space_methods_remove(blade_space_t *bs, blade_method_t *bm)
|
||||||
|
{
|
||||||
|
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
ks_assert(bs);
|
||||||
|
ks_assert(bm);
|
||||||
|
|
||||||
|
name = blade_method_name_get(bm);
|
||||||
|
ks_assert(name);
|
||||||
|
|
||||||
|
ks_hash_write_lock(bs->methods);
|
||||||
|
ks_hash_remove(bs->methods, (void *)name);
|
||||||
|
ks_hash_write_unlock(bs->methods);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
KS_DECLARE(blade_method_t *) blade_space_methods_get(blade_space_t *bs, const char *name)
|
||||||
|
{
|
||||||
|
blade_method_t *bm = NULL;
|
||||||
|
|
||||||
|
ks_assert(bs);
|
||||||
|
ks_assert(name);
|
||||||
|
|
||||||
|
ks_hash_read_lock(bs->methods);
|
||||||
|
bm = ks_hash_search(bs->methods, (void *)name, KS_UNLOCKED);
|
||||||
|
ks_hash_read_unlock(bs->methods);
|
||||||
|
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* For Emacs:
|
||||||
|
* Local Variables:
|
||||||
|
* mode:c
|
||||||
|
* indent-tabs-mode:t
|
||||||
|
* tab-width:4
|
||||||
|
* c-basic-offset:4
|
||||||
|
* End:
|
||||||
|
* For VIM:
|
||||||
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||||
|
*/
|
@ -48,6 +48,7 @@ struct blade_handle_s {
|
|||||||
config_setting_t *config_datastore;
|
config_setting_t *config_datastore;
|
||||||
|
|
||||||
ks_hash_t *transports; // registered transports exposed by modules, NOT active connections
|
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_identity_t *identity;
|
||||||
blade_datastore_t *datastore;
|
blade_datastore_t *datastore;
|
||||||
@ -69,6 +70,7 @@ struct blade_handle_transport_registration_s {
|
|||||||
blade_transport_callbacks_t *callbacks;
|
blade_transport_callbacks_t *callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_handle_transport_registration_create(blade_handle_transport_registration_t **bhtrP,
|
KS_DECLARE(ks_status_t) blade_handle_transport_registration_create(blade_handle_transport_registration_t **bhtrP,
|
||||||
ks_pool_t *pool,
|
ks_pool_t *pool,
|
||||||
blade_module_t *module,
|
blade_module_t *module,
|
||||||
@ -133,6 +135,8 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo
|
|||||||
|
|
||||||
ks_hash_create(&bh->transports, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
|
ks_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_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_hash_create(&bh->connections, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
|
||||||
ks_assert(bh->connections);
|
ks_assert(bh->connections);
|
||||||
@ -144,6 +148,8 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo
|
|||||||
|
|
||||||
*bhP = bh;
|
*bhP = bh;
|
||||||
|
|
||||||
|
ks_log(KS_LOG_DEBUG, "Created\n");
|
||||||
|
|
||||||
return KS_STATUS_SUCCESS;
|
return KS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,10 +174,13 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP)
|
|||||||
ks_hash_destroy(&bh->requests);
|
ks_hash_destroy(&bh->requests);
|
||||||
ks_hash_destroy(&bh->sessions);
|
ks_hash_destroy(&bh->sessions);
|
||||||
ks_hash_destroy(&bh->connections);
|
ks_hash_destroy(&bh->connections);
|
||||||
|
ks_hash_destroy(&bh->spaces);
|
||||||
ks_hash_destroy(&bh->transports);
|
ks_hash_destroy(&bh->transports);
|
||||||
|
|
||||||
if (bh->tpool && (flags & BH_MYTPOOL)) ks_thread_pool_destroy(&bh->tpool);
|
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);
|
ks_pool_free(bh->pool, &bh);
|
||||||
|
|
||||||
if (pool && (flags & BH_MYPOOL)) {
|
if (pool && (flags & BH_MYPOOL)) {
|
||||||
@ -249,13 +258,22 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh)
|
|||||||
blade_session_t *value = NULL;
|
blade_session_t *value = NULL;
|
||||||
|
|
||||||
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
|
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);
|
blade_session_hangup(value);
|
||||||
}
|
}
|
||||||
while (ks_hash_count(bh->sessions) > 0) ks_sleep_ms(100);
|
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
|
// @todo unload DSOs
|
||||||
|
|
||||||
@ -316,11 +334,81 @@ KS_DECLARE(ks_status_t) blade_handle_transport_unregister(blade_handle_t *bh, co
|
|||||||
if (bhtr) ks_hash_remove(bh->transports, (void *)name);
|
if (bhtr) ks_hash_remove(bh->transports, (void *)name);
|
||||||
ks_hash_write_unlock(bh->transports);
|
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;
|
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_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;
|
ks_status_t ret = KS_STATUS_SUCCESS;
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2007-2014, Anthony Minessale II
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of the original author; nor the names of any contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "blade.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Find bootstrap addr.
|
|
||||||
Make a WSS connection to get validated and get group keys.
|
|
||||||
Broadcast/Announce existence.
|
|
||||||
|
|
||||||
|
|
||||||
HEADER
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| Ver |r|R|U|U| Channel no | Packet Length |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| SEQ |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| PAYLOAD ...... |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
|
|
||||||
r = IS Response
|
|
||||||
R = IS Retransmission
|
|
||||||
U = Unused
|
|
||||||
|
|
||||||
PAYLOAD
|
|
||||||
|
|
||||||
0 1 2 3
|
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| Instruction | Datatype | Length |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
| PAYLOAD ..... |
|
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct bpcp_header_s {
|
|
||||||
uint32_t header;
|
|
||||||
uint64_t seq;
|
|
||||||
} bpcp_header_t;
|
|
||||||
|
|
||||||
typedef struct bpcp_channel_nfo_s {
|
|
||||||
char *channel_name;
|
|
||||||
unsigned char key[crypto_generichash_BYTES];
|
|
||||||
uint32_t ttl;
|
|
||||||
} bpcp_channel_nfo_t;
|
|
||||||
|
|
||||||
typedef struct bpcp_handle_s {
|
|
||||||
ks_socket_t sock;
|
|
||||||
ks_sockaddr_t local_addr;
|
|
||||||
ks_sockaddr_t bootstrap_addr;
|
|
||||||
ks_hash_t *channel_nfo_hash;
|
|
||||||
} bpcp_handle_t;
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) bpcp_create(bpcp_handle_t **handle,
|
|
||||||
const char *local_addr, ks_port_t local_port,
|
|
||||||
const char *bootstrap_addr, ks_port_t bootstrap_port)
|
|
||||||
{
|
|
||||||
return KS_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For Emacs:
|
|
||||||
* Local Variables:
|
|
||||||
* mode:c
|
|
||||||
* indent-tabs-mode:t
|
|
||||||
* tab-width:4
|
|
||||||
* c-basic-offset:4
|
|
||||||
* End:
|
|
||||||
* For VIM:
|
|
||||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
|
||||||
*/
|
|
@ -46,7 +46,8 @@
|
|||||||
#include "blade_session.h"
|
#include "blade_session.h"
|
||||||
#include "blade_protocol.h"
|
#include "blade_protocol.h"
|
||||||
#include "blade_datastore.h"
|
#include "blade_datastore.h"
|
||||||
#include "bpcp.h"
|
#include "blade_space.h"
|
||||||
|
#include "blade_method.h"
|
||||||
|
|
||||||
KS_BEGIN_EXTERN_C
|
KS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2007-2014, Anthony Minessale II
|
* Copyright (c) 2017, Shane Bryldt
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,12 +31,15 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BPCP_H_
|
#ifndef _BLADE_METHOD_H_
|
||||||
#define _BPCP_H_
|
#define _BLADE_METHOD_H_
|
||||||
#include <blade.h>
|
#include <blade.h>
|
||||||
|
|
||||||
KS_BEGIN_EXTERN_C
|
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
|
KS_END_EXTERN_C
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -36,10 +36,17 @@
|
|||||||
#include <blade.h>
|
#include <blade.h>
|
||||||
|
|
||||||
KS_BEGIN_EXTERN_C
|
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_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_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_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
|
KS_END_EXTERN_C
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,166 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017, FreeSWITCH LLC
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of the original author; nor the names of any contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _BLADE_RPCPROTO_H_
|
|
||||||
#define _BLADE_RPCPROTO_H_
|
|
||||||
|
|
||||||
#include <ks_rpcmessage.h>
|
|
||||||
#include <blade_types.h>
|
|
||||||
|
|
||||||
// temp typedefs to get compile going
|
|
||||||
//typedef struct blade_peer_s blade_peer_t;
|
|
||||||
//typedef struct blade_event_s blade_event_t;
|
|
||||||
|
|
||||||
#define KS_RPCMESSAGE_NAMESPACE_LENGTH 16
|
|
||||||
#define KS_RPCMESSAGE_COMMAND_LENGTH 238
|
|
||||||
#define KS_RPCMESSAGE_FQCOMMAND_LENGTH (KS_RPCMESSAGE_NAMESPACE_LENGTH+KS_RPCMESSAGE_COMMAND_LENGTH+1)
|
|
||||||
#define KS_RPCMESSAGE_VERSION_LENGTH 9
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* contents to add to the "blade" field in rpc
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct blade_rpc_fields_s {
|
|
||||||
|
|
||||||
const char *to;
|
|
||||||
const char *from;
|
|
||||||
const char *token;
|
|
||||||
|
|
||||||
} blade_rpc_fields_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum jrpc_status_t {
|
|
||||||
JRPC_PASS = (1 << 0),
|
|
||||||
JRPC_SEND = (1 << 1),
|
|
||||||
JRPC_EXIT = (1 << 2),
|
|
||||||
JRPC_SEND_EXIT = JRPC_SEND + JRPC_EXIT,
|
|
||||||
JRPC_ERROR = (1 << 3)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum jrpc_status_t (*jrpc_func_t) (cJSON *request, cJSON **replyP);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* setup
|
|
||||||
* -----
|
|
||||||
*/
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_init(ks_pool_t *pool);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* namespace and call back registration
|
|
||||||
* ------------------------------------
|
|
||||||
*/
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_declare_namespace(char* namespace, const char* version);
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_register_function(char* namespace,
|
|
||||||
char *command,
|
|
||||||
jrpc_func_t func,
|
|
||||||
jrpc_func_t respfunc);
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_register_custom_request_function(char* namespace,
|
|
||||||
char *command,
|
|
||||||
jrpc_func_t prefix_func,
|
|
||||||
jrpc_func_t postfix_func);
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_register_custom_response_function(char *namespace,
|
|
||||||
char *command,
|
|
||||||
jrpc_func_t prefix_func,
|
|
||||||
jrpc_func_t postfix_func);
|
|
||||||
KS_DECLARE(void) blade_rpc_remove_namespace(char* namespace);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* template registration and inheritance
|
|
||||||
* -------------------------------------
|
|
||||||
*/
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_declare_template(char* templatename, const char* version);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t)blade_rpc_register_template_function(char *name,
|
|
||||||
char *command,
|
|
||||||
jrpc_func_t func,
|
|
||||||
jrpc_func_t respfunc);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t)blade_rpc_inherit_template(char *namespace, char* template);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* create a request message
|
|
||||||
*/
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_request(char *namespace,
|
|
||||||
char *method,
|
|
||||||
blade_rpc_fields_t* fields,
|
|
||||||
cJSON **paramsP,
|
|
||||||
cJSON **requestP);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_response(cJSON *request,
|
|
||||||
cJSON **reply,
|
|
||||||
cJSON **response);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) blade_rpc_create_errorresponse(cJSON *request,
|
|
||||||
cJSON **reply,
|
|
||||||
cJSON **response);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_parse_message(cJSON *message,
|
|
||||||
char **namespace,
|
|
||||||
char **method,
|
|
||||||
char **version,
|
|
||||||
uint32_t *idP,
|
|
||||||
blade_rpc_fields_t **fieldsP);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* peer create/destroy
|
|
||||||
* -------------------
|
|
||||||
*/
|
|
||||||
//KS_DECLARE(ks_status_t) blade_rpc_onconnect(ks_pool_t *pool, blade_peer_t* peer);
|
|
||||||
//KS_DECLARE(ks_status_t) blade_rpc_disconnect(blade_peer_t* peer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* send message
|
|
||||||
* ------------
|
|
||||||
*/
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_write(char *sessionid, char* data, uint32_t size); //uuid_t ?
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_write_json(cJSON* json);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* process inbound message
|
|
||||||
* -----------------------
|
|
||||||
*/
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_process_data(const uint8_t *data, ks_size_t size);
|
|
||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_rpc_process_jsonmessage(cJSON *request);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -52,7 +52,7 @@ KS_DECLARE(void) blade_session_hangup(blade_session_t *bs);
|
|||||||
KS_DECLARE(ks_bool_t) blade_session_terminating(blade_session_t *bs);
|
KS_DECLARE(ks_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_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_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_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_sending_pop(blade_session_t *bs, cJSON **json);
|
||||||
KS_DECLARE(ks_status_t) blade_session_receiving_push(blade_session_t *bs, cJSON *json);
|
KS_DECLARE(ks_status_t) blade_session_receiving_push(blade_session_t *bs, cJSON *json);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, FreeSWITCH Solutions LLC
|
* Copyright (c) 2017, Shane Bryldt
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,56 +31,21 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _BLADE_SPACE_H_
|
||||||
#ifndef _KS_RPCMESSAGE_H_
|
#define _BLADE_SPACE_H_
|
||||||
#define _KS_RPCMESSAGE_H_
|
#include <blade.h>
|
||||||
|
|
||||||
#include "ks.h"
|
|
||||||
|
|
||||||
KS_BEGIN_EXTERN_C
|
KS_BEGIN_EXTERN_C
|
||||||
|
KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, const char *path);
|
||||||
#define KS_RPCMESSAGE_NAMESPACE_LENGTH 16
|
KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP);
|
||||||
#define KS_RPCMESSAGE_COMMAND_LENGTH 238
|
KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs);
|
||||||
#define KS_RPCMESSAGE_FQCOMMAND_LENGTH (KS_RPCMESSAGE_NAMESPACE_LENGTH+KS_RPCMESSAGE_COMMAND_LENGTH+1)
|
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs);
|
||||||
#define KS_RPCMESSAGE_VERSION_LENGTH 9
|
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);
|
||||||
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_END_EXTERN_C
|
KS_END_EXTERN_C
|
||||||
|
|
||||||
#endif /* defined(_KS_RPCMESSAGE_H_) */
|
#endif
|
||||||
|
|
||||||
/* For Emacs:
|
/* For Emacs:
|
||||||
* Local Variables:
|
* Local Variables:
|
@ -50,6 +50,11 @@ KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh);
|
|||||||
|
|
||||||
KS_DECLARE(ks_status_t) blade_handle_transport_register(blade_handle_t *bh, blade_module_t *bm, const char *name, blade_transport_callbacks_t *callbacks);
|
KS_DECLARE(ks_status_t) blade_handle_transport_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_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(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);
|
KS_DECLARE(blade_connection_t *) blade_handle_connections_get(blade_handle_t *bh, const char *cid);
|
||||||
|
@ -47,6 +47,12 @@ typedef struct blade_connection_s blade_connection_t;
|
|||||||
typedef struct blade_session_s blade_session_t;
|
typedef struct blade_session_s blade_session_t;
|
||||||
typedef struct blade_request_s blade_request_t;
|
typedef struct blade_request_s blade_request_t;
|
||||||
typedef struct blade_response_s blade_response_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;
|
typedef struct blade_datastore_s blade_datastore_t;
|
||||||
|
|
||||||
@ -147,6 +153,7 @@ struct blade_request_s {
|
|||||||
|
|
||||||
cJSON *message;
|
cJSON *message;
|
||||||
const char *message_id; // pulled from message for easier keying
|
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 ttl to wait for response before injecting an error response locally
|
||||||
// @todo rpc response callback
|
// @todo rpc response callback
|
||||||
};
|
};
|
||||||
|
@ -3,11 +3,6 @@ TEST_LDADD = $(abs_top_builddir)/libblade.la -lconfig -lm -lpthread
|
|||||||
check_PROGRAMS =
|
check_PROGRAMS =
|
||||||
|
|
||||||
|
|
||||||
check_PROGRAMS += testrpcproto
|
|
||||||
testrpcproto_SOURCES = testrpcproto.c tap.c
|
|
||||||
testrpcproto_CFLAGS = $(AM_CFLAGS)
|
|
||||||
testrpcproto_LDADD = $(TEST_LDADD)
|
|
||||||
|
|
||||||
check_PROGRAMS += testbuild
|
check_PROGRAMS += testbuild
|
||||||
testbuild_SOURCES = testbuild.c tap.c
|
testbuild_SOURCES = testbuild.c tap.c
|
||||||
testbuild_CFLAGS = $(AM_CFLAGS)
|
testbuild_CFLAGS = $(AM_CFLAGS)
|
||||||
|
@ -1,724 +0,0 @@
|
|||||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
||||||
|
|
||||||
|
|
||||||
#include <blade_rpcproto.h>
|
|
||||||
|
|
||||||
#pragma GCC optimize ("O0")
|
|
||||||
|
|
||||||
|
|
||||||
ks_pool_t *pool;
|
|
||||||
ks_thread_pool_t *tpool;
|
|
||||||
|
|
||||||
|
|
||||||
static ks_thread_t *threads[10];
|
|
||||||
|
|
||||||
static char idbuffer[51];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_widget(cJSON *msg, cJSON **response)
|
|
||||||
{
|
|
||||||
printf("entering process_widget\n");
|
|
||||||
|
|
||||||
char *b0 = cJSON_PrintUnformatted(msg);
|
|
||||||
printf("Request: %s\n", b0);
|
|
||||||
ks_pool_free(pool, &b0);
|
|
||||||
|
|
||||||
cJSON *resp = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(resp, "code", 199);
|
|
||||||
|
|
||||||
//ks_rpcmessageid_t msgid = ks_rpcmessage_create_response(msg, &resp, response);
|
|
||||||
ks_rpcmessageid_t msgid = blade_rpc_create_response(msg, &resp, response);
|
|
||||||
|
|
||||||
char *b1 = cJSON_PrintUnformatted(*response); //(*response);
|
|
||||||
printf("Response: msgid %d\n%s\n", msgid, b1);
|
|
||||||
ks_pool_free(pool, &b1);
|
|
||||||
|
|
||||||
printf("exiting process_wombat\n");
|
|
||||||
|
|
||||||
return JRPC_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_widget_response(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
printf("entering process_widget_response\n");
|
|
||||||
printf("exiting process_widget_response\n");
|
|
||||||
return JRPC_PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat(cJSON *msg, cJSON **replyP)
|
|
||||||
{
|
|
||||||
printf("entering process_wombat\n");
|
|
||||||
|
|
||||||
char *b0 = cJSON_PrintUnformatted(msg);
|
|
||||||
printf("\nRequest: %s\n\n", b0);
|
|
||||||
ks_pool_free(pool, &b0);
|
|
||||||
|
|
||||||
cJSON *result = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(result, "code", 99);
|
|
||||||
cJSON *response;
|
|
||||||
|
|
||||||
// ks_rpcmessageid_t msgid = ks_rpcmessage_create_response(msg, &result, &response);
|
|
||||||
ks_rpcmessageid_t msgid = blade_rpc_create_response(msg, &result, &response);
|
|
||||||
|
|
||||||
cJSON *response_copy = cJSON_Duplicate(response, 1);
|
|
||||||
blade_rpc_process_jsonmessage(response_copy);
|
|
||||||
|
|
||||||
if (msgid != 0) {
|
|
||||||
char *b1 = cJSON_PrintUnformatted(response); //(*response);
|
|
||||||
printf("\nResponse: msgid %d\n%s\n\n", msgid, b1);
|
|
||||||
blade_rpc_write_json(response);
|
|
||||||
ks_pool_free(pool, &b1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printf("process_wombat: unable to create response \n");
|
|
||||||
return JRPC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
blade_rpc_fields_t *r_fields;
|
|
||||||
|
|
||||||
char *r_method;
|
|
||||||
char *r_namespace;
|
|
||||||
char *r_version;
|
|
||||||
uint32_t r_id;
|
|
||||||
|
|
||||||
ks_status_t s1 = blade_rpc_parse_message(msg, &r_namespace, &r_method, &r_version, &r_id, &r_fields);
|
|
||||||
|
|
||||||
if (s1 == KS_STATUS_FAIL) {
|
|
||||||
printf("process_wombat: blade_rpc_parse_message failed\n");
|
|
||||||
return JRPC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nprocess_wombat: blade_rpc_parse_message namespace %s, method %s, id %d, version %s, to %s, from %s, token %s\n\n",
|
|
||||||
r_namespace, r_method, r_id, r_version,
|
|
||||||
r_fields->to, r_fields->from, r_fields->token);
|
|
||||||
|
|
||||||
cJSON *parms2 = NULL;
|
|
||||||
|
|
||||||
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
|
|
||||||
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
|
|
||||||
char token[] = "abcdefhgjojklmnopqrst";
|
|
||||||
|
|
||||||
blade_rpc_fields_t fields;
|
|
||||||
fields.to = to;
|
|
||||||
fields.from = from;
|
|
||||||
fields.token = token;
|
|
||||||
|
|
||||||
// msgid = ks_rpcmessage_create_request("app1", "widget", &parms2, replyP);
|
|
||||||
msgid = blade_rpc_create_request(r_namespace, r_method, &fields, NULL, replyP);
|
|
||||||
|
|
||||||
if (!msgid) {
|
|
||||||
printf("process wombat: create of next request failed\n");
|
|
||||||
return JRPC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
b0 = cJSON_PrintUnformatted(*replyP);
|
|
||||||
|
|
||||||
if (!b0) {
|
|
||||||
printf("process wombat: create of next request cannot be formatted\n");
|
|
||||||
return JRPC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
printf("\nprocess wombat: next request\n%s\n\n", b0);
|
|
||||||
|
|
||||||
|
|
||||||
printf("\n\nexiting process_wombat with a reply to send\n");
|
|
||||||
|
|
||||||
return JRPC_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat_prerequest(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
printf("entering process_wombat_prerequest\n");
|
|
||||||
printf("exiting process_wombat_prerequest\n");
|
|
||||||
return JRPC_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat_postrequest(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
printf("entering process_wombat_postrequest\n");
|
|
||||||
printf("exiting process_wombat_postrequest\n");
|
|
||||||
return JRPC_PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat_response(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
printf("entering process_wombat_response\n");
|
|
||||||
printf("exiting process_wombat_response\n");
|
|
||||||
return JRPC_PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat_preresponse(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
|
|
||||||
printf("entering process_wombat_preresponse\n");
|
|
||||||
|
|
||||||
cJSON *response = NULL;
|
|
||||||
cJSON *result = NULL;
|
|
||||||
|
|
||||||
cJSON *parms2 = NULL;
|
|
||||||
|
|
||||||
//ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "widget", &parms2, msg);
|
|
||||||
|
|
||||||
printf("exiting process_wombat_preresponse\n");
|
|
||||||
return JRPC_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_wombat_postresponse(cJSON *request, cJSON **msg)
|
|
||||||
{
|
|
||||||
printf("entering process_postwombat_response\n");
|
|
||||||
printf("exiting process_postwombat_response\n");
|
|
||||||
return JRPC_PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static enum jrpc_status_t process_badbunny( cJSON *msg, cJSON **response)
|
|
||||||
{
|
|
||||||
printf("entering process_badbunny\n");
|
|
||||||
|
|
||||||
char *b0 = cJSON_PrintUnformatted(msg);
|
|
||||||
printf("\nRequest: %s\n\n", b0);
|
|
||||||
ks_pool_free(pool, &b0);
|
|
||||||
|
|
||||||
cJSON *respvalue;
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_create_errorresponse(msg, &respvalue, response);
|
|
||||||
|
|
||||||
char *b2 = cJSON_PrintUnformatted(*response);
|
|
||||||
printf("\nRequest: msgid %d\n%s\n\n", msgid, b2);
|
|
||||||
ks_pool_free(pool, &b2);
|
|
||||||
|
|
||||||
//cJSON *respvalue = cJSON_CreateNumber(1);
|
|
||||||
|
|
||||||
|
|
||||||
char *b1 = cJSON_PrintUnformatted(*response); //(*response);
|
|
||||||
printf("\nResponse: %s\n\n", b1);
|
|
||||||
ks_pool_free(pool, &b1);
|
|
||||||
|
|
||||||
printf("exiting process_badbunny\n");
|
|
||||||
|
|
||||||
|
|
||||||
return JRPC_SEND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void test01()
|
|
||||||
{
|
|
||||||
printf("**** testrpcmessages - test01 start\n"); fflush(stdout);
|
|
||||||
|
|
||||||
blade_rpc_declare_template("temp1", "1.0");
|
|
||||||
|
|
||||||
blade_rpc_register_template_function("temp1", "widget", process_widget, process_widget_response);
|
|
||||||
|
|
||||||
blade_rpc_declare_namespace("app1", "1.0");
|
|
||||||
|
|
||||||
blade_rpc_register_function("app1", "wombat", process_wombat, process_wombat_response);
|
|
||||||
|
|
||||||
blade_rpc_register_custom_request_function("app1", "wombat", process_wombat_prerequest, process_wombat_postresponse);
|
|
||||||
blade_rpc_register_custom_response_function("app1", "wombat", process_wombat_preresponse, process_wombat_postresponse);
|
|
||||||
|
|
||||||
|
|
||||||
/* message 1 */
|
|
||||||
/* --------- */
|
|
||||||
cJSON* request1 = NULL;
|
|
||||||
cJSON* parms1 = NULL;
|
|
||||||
|
|
||||||
printf("\n\n\n - test01 message1 - basic message\n\n\n");
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "wombat", &parms1, &request1);
|
|
||||||
if (msgid == 0) {
|
|
||||||
printf("test01.1: unable to create message 1\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!request1) {
|
|
||||||
printf("test01.1: No json returned from create request 1\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_AddStringToObject(parms1, "hello", "cruel world");
|
|
||||||
|
|
||||||
char *pdata = cJSON_PrintUnformatted(request1);
|
|
||||||
|
|
||||||
if (!pdata) {
|
|
||||||
printf("test01.1: unable to parse cJSON object\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("test01 request:\n%s\n", pdata);
|
|
||||||
|
|
||||||
|
|
||||||
blade_rpc_process_jsonmessage(request1);
|
|
||||||
|
|
||||||
cJSON_Delete(request1);
|
|
||||||
|
|
||||||
ks_pool_free(pool, &pdata);
|
|
||||||
|
|
||||||
printf("\ntest01.1 complete\n");
|
|
||||||
|
|
||||||
|
|
||||||
/* message 2 */
|
|
||||||
/* --------- */
|
|
||||||
|
|
||||||
printf("\n\n\n test01 - message2 - test inherit\n\n\n");
|
|
||||||
|
|
||||||
blade_rpc_inherit_template("app1", "temp1");
|
|
||||||
|
|
||||||
cJSON* request2 = NULL;
|
|
||||||
cJSON* parms2 = cJSON_CreateObject();
|
|
||||||
|
|
||||||
cJSON_AddStringToObject(parms2, "hello2", "cruel world once again");
|
|
||||||
|
|
||||||
msgid = ks_rpcmessage_create_request("app1", "temp1.widget", &parms2, &request2);
|
|
||||||
if (msgid == 0) {
|
|
||||||
printf("test01.2: failed to create a wombat\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!request2) {
|
|
||||||
printf("test01.2: No json returned from create request 1\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdata = cJSON_PrintUnformatted(request2);
|
|
||||||
|
|
||||||
if (!pdata) {
|
|
||||||
printf("test01.2: unable to parse cJSON object\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\ntest01 request:\n%s\n\n\n", pdata);
|
|
||||||
|
|
||||||
blade_rpc_process_jsonmessage(request2);
|
|
||||||
|
|
||||||
cJSON_Delete(request2);
|
|
||||||
ks_pool_free(pool, &pdata);
|
|
||||||
|
|
||||||
printf("\ntest01.2 complete\n");
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void test02()
|
|
||||||
{
|
|
||||||
printf("**** testrpcmessages - test02 start\n"); fflush(stdout);
|
|
||||||
|
|
||||||
blade_rpc_declare_namespace("app2", "1.0");
|
|
||||||
|
|
||||||
blade_rpc_register_function("app2", "wombat", process_wombat, process_wombat_response);
|
|
||||||
|
|
||||||
blade_rpc_inherit_template("app2", "temp1");
|
|
||||||
|
|
||||||
blade_rpc_register_custom_request_function("app2", "wombat", process_wombat_prerequest, process_wombat_postresponse);
|
|
||||||
blade_rpc_register_custom_response_function("app2", "wombat", process_wombat_preresponse, process_wombat_postresponse);
|
|
||||||
|
|
||||||
blade_rpc_register_function("app2", "bunny", process_badbunny, NULL);
|
|
||||||
|
|
||||||
char to[] = "tony@freeswitch.com/laptop?transport=wss&host=server1.freeswitch.com&port=1234";
|
|
||||||
char from[] = "colm@freeswitch.com/laptop?transport=wss&host=server2.freeswitch.com&port=4321";
|
|
||||||
char token[] = "abcdefhgjojklmnopqrst";
|
|
||||||
|
|
||||||
blade_rpc_fields_t fields;
|
|
||||||
fields.to = to;
|
|
||||||
fields.from = from;
|
|
||||||
fields.token = token;
|
|
||||||
|
|
||||||
|
|
||||||
/* test the 4 different ways to handle param messages */
|
|
||||||
|
|
||||||
cJSON *params1 = NULL;
|
|
||||||
cJSON *request1;
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = blade_rpc_create_request("app2", "temp1.widget2", &fields, ¶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;
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ lib_LTLIBRARIES = libks.la
|
|||||||
libks_la_SOURCES = src/ks.c src/ks_string.c src/ks_json.c src/cJSON.c src/cJSON_Utils.c src/ks_thread.c src/ks_thread_pool.c src/ks_mutex.c src/ks_config.c
|
libks_la_SOURCES = src/ks.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_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_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_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/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.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
|
||||||
@ -30,13 +30,9 @@ library_include_HEADERS += src/include/ks_thread_pool.h src/include/ks_cJSON.h s
|
|||||||
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_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_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_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_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_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
|
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
|
tests: libks.la
|
||||||
$(MAKE) -C test tests
|
$(MAKE) -C test tests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,7 +137,6 @@ KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
|
|||||||
#include "ks_bencode.h"
|
#include "ks_bencode.h"
|
||||||
#include "ks_rng.h"
|
#include "ks_rng.h"
|
||||||
#include "ks_acl.h"
|
#include "ks_acl.h"
|
||||||
#include "ks_rpcmessage.h"
|
|
||||||
#include "ks_base64.h"
|
#include "ks_base64.h"
|
||||||
|
|
||||||
KS_END_EXTERN_C
|
KS_END_EXTERN_C
|
||||||
|
@ -1,317 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 FreeSWITCH Solutions LLC
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of the original author; nor the names of any contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
|
||||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma GCC optimize ("O0")
|
|
||||||
|
|
||||||
|
|
||||||
#include <ks.h>
|
|
||||||
#include <ks_rpcmessage.h>
|
|
||||||
#include <ks_buffer.h>
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
|
|
||||||
ks_mutex_t *id_mutex;
|
|
||||||
uint32_t message_id;
|
|
||||||
|
|
||||||
ks_pool_t *pool;
|
|
||||||
|
|
||||||
} handle = {NULL, 0, NULL};
|
|
||||||
|
|
||||||
const char PROTOCOL[] = "jsonrpc";
|
|
||||||
const char PROTOCOL_VERSION[] = "2.0";
|
|
||||||
const char ID[] = "id";
|
|
||||||
const char METHOD[] = "method";
|
|
||||||
const char PARAMS[] = "params";
|
|
||||||
const char ERROR[] = "error";
|
|
||||||
const char RESULT[] = "result";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(void*) ks_json_pool_alloc(ks_size_t size)
|
|
||||||
{
|
|
||||||
return ks_pool_alloc(handle.pool, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
KS_DECLARE(void) ks_json_pool_free(void *ptr)
|
|
||||||
{
|
|
||||||
ks_pool_free(handle.pool, &ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(void) ks_rpcmessage_init(ks_pool_t* pool)
|
|
||||||
{
|
|
||||||
if (!handle.id_mutex) {
|
|
||||||
ks_mutex_create(&handle.id_mutex, KS_MUTEX_FLAG_DEFAULT, pool);
|
|
||||||
handle.pool = pool;
|
|
||||||
|
|
||||||
cJSON_Hooks hooks;
|
|
||||||
hooks.malloc_fn = ks_json_pool_alloc;
|
|
||||||
hooks.free_fn = ks_json_pool_free;
|
|
||||||
cJSON_InitHooks(&hooks);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t ks_rpcmessage_next_id()
|
|
||||||
{
|
|
||||||
uint32_t message_id;
|
|
||||||
|
|
||||||
ks_mutex_lock(handle.id_mutex);
|
|
||||||
|
|
||||||
++handle.message_id;
|
|
||||||
|
|
||||||
if (!handle.message_id) {
|
|
||||||
++handle.message_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
message_id = handle.message_id;
|
|
||||||
|
|
||||||
ks_mutex_unlock(handle.id_mutex);
|
|
||||||
|
|
||||||
return message_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static cJSON *ks_rpcmessage_new(uint32_t id)
|
|
||||||
{
|
|
||||||
cJSON *obj = cJSON_CreateObject();
|
|
||||||
cJSON_AddItemToObject(obj, PROTOCOL, cJSON_CreateString(PROTOCOL_VERSION));
|
|
||||||
|
|
||||||
if (id) {
|
|
||||||
cJSON_AddItemToObject(obj, ID, cJSON_CreateNumber(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cJSON *ks_rpcmessage_dup(cJSON *msgid)
|
|
||||||
{
|
|
||||||
cJSON *obj = cJSON_CreateObject();
|
|
||||||
cJSON_AddItemToObject(obj, PROTOCOL, cJSON_CreateString(PROTOCOL_VERSION));
|
|
||||||
|
|
||||||
if (msgid) {
|
|
||||||
cJSON_AddItemToObject(obj, ID, cJSON_Duplicate(msgid, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrequest(cJSON *msg)
|
|
||||||
{
|
|
||||||
cJSON *result = cJSON_GetObjectItem(msg, RESULT);
|
|
||||||
cJSON *error = cJSON_GetObjectItem(msg, ERROR);
|
|
||||||
|
|
||||||
if (result || error) {
|
|
||||||
return KS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return KS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
KS_DECLARE(ks_bool_t) ks_rpcmessage_isrpc(cJSON *msg)
|
|
||||||
{
|
|
||||||
cJSON *rpc = cJSON_GetObjectItem(msg, PROTOCOL);
|
|
||||||
|
|
||||||
if (rpc) {
|
|
||||||
return KS_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return KS_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_request(char *namespace,
|
|
||||||
char *command,
|
|
||||||
cJSON **paramsP,
|
|
||||||
cJSON **requestP)
|
|
||||||
{
|
|
||||||
cJSON *msg, *params = NULL;
|
|
||||||
*requestP = NULL;
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_next_id();
|
|
||||||
msg = ks_rpcmessage_new(msgid);
|
|
||||||
|
|
||||||
if (paramsP) {
|
|
||||||
|
|
||||||
if (*paramsP) { /* parameters have been passed */
|
|
||||||
params = *paramsP;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
params = cJSON_CreateObject();
|
|
||||||
*paramsP = params;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(msg, PARAMS, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
char fqcommand[KS_RPCMESSAGE_FQCOMMAND_LENGTH];
|
|
||||||
memset(fqcommand, 0, sizeof(fqcommand));
|
|
||||||
|
|
||||||
sprintf(fqcommand, "%s.%s", namespace, command);
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(msg, METHOD, cJSON_CreateString(fqcommand));
|
|
||||||
|
|
||||||
*requestP = msg;
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
KS_DECLARE(ks_size_t) ks_rpc_create_buffer(char *namespace,
|
|
||||||
char *method,
|
|
||||||
cJSON **params,
|
|
||||||
ks_buffer_t *buffer)
|
|
||||||
{
|
|
||||||
|
|
||||||
cJSON *message;
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request(namespace, method, params, &message);
|
|
||||||
|
|
||||||
if (!msgid) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (*params)->child == NULL) {
|
|
||||||
cJSON_AddNullToObject(*params, "bladenull");
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* b = cJSON_PrintUnformatted(message);
|
|
||||||
ks_size_t size = strlen(b);
|
|
||||||
|
|
||||||
ks_buffer_write(buffer, b, size);
|
|
||||||
cJSON_Delete(message);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ks_rpcmessageid_t ks_rpcmessage_get_messageid(const cJSON *msg, cJSON **cmsgidP)
|
|
||||||
{
|
|
||||||
ks_rpcmessageid_t msgid = 0;
|
|
||||||
|
|
||||||
cJSON *cmsgid = cJSON_GetObjectItem(msg, ID);
|
|
||||||
|
|
||||||
if (cmsgid->type == cJSON_Number) {
|
|
||||||
msgid = (ks_rpcmessageid_t) cmsgid->valueint;
|
|
||||||
}
|
|
||||||
|
|
||||||
*cmsgidP = cmsgid;
|
|
||||||
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ks_rpcmessageid_t ks_rpcmessage_new_response(
|
|
||||||
const cJSON *request,
|
|
||||||
cJSON **result,
|
|
||||||
cJSON **pmsg)
|
|
||||||
{
|
|
||||||
cJSON *respmsg = NULL;
|
|
||||||
cJSON *cmsgid = NULL;
|
|
||||||
|
|
||||||
cJSON *command = cJSON_GetObjectItem(request, METHOD);
|
|
||||||
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_get_messageid(request, &cmsgid );
|
|
||||||
|
|
||||||
if (!msgid || !command) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*pmsg = respmsg = ks_rpcmessage_dup(cmsgid);
|
|
||||||
|
|
||||||
cJSON_AddItemToObject(respmsg, METHOD, cJSON_Duplicate(command, 0));
|
|
||||||
|
|
||||||
if (result && *result) {
|
|
||||||
cJSON_AddItemToObject(respmsg, RESULT, *result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_response(
|
|
||||||
const cJSON *request,
|
|
||||||
cJSON **resultP,
|
|
||||||
cJSON **responseP)
|
|
||||||
{
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_new_response(request, resultP, responseP);
|
|
||||||
|
|
||||||
cJSON *respmsg = *responseP;
|
|
||||||
|
|
||||||
if (msgid) {
|
|
||||||
|
|
||||||
if (resultP && *resultP == NULL) {
|
|
||||||
cJSON *result = cJSON_CreateObject();
|
|
||||||
*resultP = result;
|
|
||||||
cJSON_AddItemToObject(respmsg, RESULT, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
KS_DECLARE(ks_rpcmessageid_t) ks_rpcmessage_create_errorresponse(
|
|
||||||
const cJSON *request,
|
|
||||||
cJSON **errorP,
|
|
||||||
cJSON **responseP)
|
|
||||||
{
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_new_response(request, NULL, responseP);
|
|
||||||
cJSON *respmsg = *responseP;
|
|
||||||
|
|
||||||
if (msgid) {
|
|
||||||
|
|
||||||
if (errorP && *errorP == NULL) {
|
|
||||||
cJSON *error = cJSON_CreateObject();
|
|
||||||
*errorP = error;
|
|
||||||
cJSON_AddItemToObject(respmsg, ERROR, error);
|
|
||||||
}
|
|
||||||
else if (errorP && *errorP) {
|
|
||||||
cJSON_AddItemToObject(*responseP, ERROR, *errorP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* For Emacs:
|
|
||||||
* Local Variables:
|
|
||||||
* mode:c
|
|
||||||
* indent-tabs-mode:t
|
|
||||||
* tab-width:4
|
|
||||||
* c-basic-offset:4
|
|
||||||
* End:
|
|
||||||
* For VIM:
|
|
||||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
|
||||||
*/
|
|
@ -4,11 +4,6 @@ check_PROGRAMS =
|
|||||||
|
|
||||||
EXTRA_DIST = tap.h
|
EXTRA_DIST = tap.h
|
||||||
|
|
||||||
check_PROGRAMS += testmessages
|
|
||||||
testmessages_SOURCES = testmessages.c tap.c
|
|
||||||
testmessages_CFLAGS = $(AM_CFLAGS)
|
|
||||||
testmessages_LDADD = $(TEST_LDADD)
|
|
||||||
|
|
||||||
check_PROGRAMS += testbuckets
|
check_PROGRAMS += testbuckets
|
||||||
testbuckets_SOURCES = testbuckets.c tap.c
|
testbuckets_SOURCES = testbuckets.c tap.c
|
||||||
testbuckets_CFLAGS = $(AM_CFLAGS)
|
testbuckets_CFLAGS = $(AM_CFLAGS)
|
||||||
@ -108,4 +103,3 @@ $(abs_top_builddir)/test/libtorrent.so: $(abs_top_builddir)/test/libtorrent.o
|
|||||||
|
|
||||||
$(abs_top_builddir)/test/libtorrent.o: $(abs_top_builddir)/test/libtorrent.cpp
|
$(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
|
g++ -c -fPIC -o $(abs_top_builddir)/test/libtorrent.o -I$(abs_top_builddir)/test/ $(abs_top_builddir)/test/libtorrent.cpp
|
||||||
|
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
||||||
|
|
||||||
#include "../src/include/ks_rpcmessage.h"
|
|
||||||
|
|
||||||
#pragma GCC optimize ("O0")
|
|
||||||
|
|
||||||
|
|
||||||
ks_pool_t *pool;
|
|
||||||
|
|
||||||
|
|
||||||
void test01()
|
|
||||||
{
|
|
||||||
printf("**** testrpcmessages - test01 start\n\n"); fflush(stdout);
|
|
||||||
|
|
||||||
cJSON* request1 = NULL;
|
|
||||||
cJSON* parms1 = NULL;
|
|
||||||
cJSON* response1 = NULL;
|
|
||||||
|
|
||||||
/*namespace, method, params, **request */
|
|
||||||
ks_rpcmessageid_t msgid = ks_rpcmessage_create_request("app1", "func1", &parms1, &request1);
|
|
||||||
if (msgid == 0) {
|
|
||||||
printf("message create failed %d\n", msgid);
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_AddStringToObject(parms1, "hello", "cruel world");
|
|
||||||
char* data = cJSON_PrintUnformatted(request1);
|
|
||||||
|
|
||||||
printf("test01 request1: %d\n%s\n\n", msgid, data);
|
|
||||||
ks_json_pool_free(data);
|
|
||||||
|
|
||||||
|
|
||||||
/* convert to buffer */
|
|
||||||
cJSON* parms2 = NULL;
|
|
||||||
ks_buffer_t *buffer;
|
|
||||||
|
|
||||||
ks_buffer_create(&buffer, 256, 256, 1024);
|
|
||||||
|
|
||||||
ks_size_t n = ks_rpc_create_buffer("app2", "func2", &parms2, buffer);
|
|
||||||
|
|
||||||
ks_size_t size = ks_buffer_len(buffer);
|
|
||||||
char *b = (char *)ks_pool_alloc(pool, size+1);
|
|
||||||
ks_buffer_read(buffer, b, size);
|
|
||||||
|
|
||||||
printf("test01 request2: %zd %zd from ks_buffer\n%s\n\n\n", n, size, b);
|
|
||||||
|
|
||||||
|
|
||||||
/* create message 3 */
|
|
||||||
|
|
||||||
cJSON *parms3 = cJSON_CreateNumber(1);
|
|
||||||
cJSON *request3 = NULL;
|
|
||||||
|
|
||||||
msgid = ks_rpcmessage_create_request("app1", "badbunny", &parms3, &request3);
|
|
||||||
data = cJSON_PrintUnformatted(request3);
|
|
||||||
printf("\ntest01i request: %d\n%s\n\n", msgid, data);
|
|
||||||
|
|
||||||
cJSON *response3 = NULL;
|
|
||||||
|
|
||||||
ks_rpcmessage_create_response(request3, NULL, &response3);
|
|
||||||
|
|
||||||
data = cJSON_PrintUnformatted(response3);
|
|
||||||
printf("\ntest01 response3: %d\n%s\n\n", msgid, data);
|
|
||||||
|
|
||||||
ks_json_pool_free(data);
|
|
||||||
cJSON_Delete(request3);
|
|
||||||
cJSON_Delete(response3);
|
|
||||||
|
|
||||||
printf("**** testrpcmessages - test01 complete\n\n\n"); fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void test02()
|
|
||||||
{
|
|
||||||
printf("**** testmessages - test02 start\n"); fflush(stdout);
|
|
||||||
|
|
||||||
printf("**** testmessages - test02 finished\n"); fflush(stdout);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
|
|
||||||
printf("testmessages - start\n");
|
|
||||||
|
|
||||||
int tests[100];
|
|
||||||
if (argc == 1) {
|
|
||||||
tests[0] = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for(int tix=1; tix<100 && tix<argc; ++tix) {
|
|
||||||
long i = strtol(argv[tix], NULL, 0);
|
|
||||||
tests[tix] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ks_init();
|
|
||||||
ks_global_set_default_logger(7);
|
|
||||||
|
|
||||||
|
|
||||||
ks_status_t status;
|
|
||||||
|
|
||||||
status = ks_pool_open(&pool);
|
|
||||||
|
|
||||||
|
|
||||||
for (int tix=0; tix<argc; ++tix) {
|
|
||||||
|
|
||||||
if (tests[tix] == 1) {
|
|
||||||
ks_rpcmessage_init(pool);
|
|
||||||
test01();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tests[tix] == 2) {
|
|
||||||
ks_rpcmessage_init(pool);
|
|
||||||
test02();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user