提交 7742dffa authored 作者: Shane Bryldt's avatar Shane Bryldt 提交者: Mike Jerris

FS-9952: Initial implementation of a very basic text chat system which…

FS-9952: Initial implementation of a very basic text chat system which introduced a number of supporting subsystems
上级 75ee4539
...@@ -15,7 +15,7 @@ libblade_la_SOURCES = src/blade.c src/blade_stack.c ...@@ -15,7 +15,7 @@ libblade_la_SOURCES = src/blade.c src/blade_stack.c
libblade_la_SOURCES += src/blade_datastore.c libblade_la_SOURCES += src/blade_datastore.c
libblade_la_SOURCES += src/blade_identity.c src/blade_module.c src/blade_connection.c libblade_la_SOURCES += src/blade_identity.c src/blade_module.c src/blade_connection.c
libblade_la_SOURCES += src/blade_session.c src/blade_protocol.c src/blade_space.c src/blade_method.c libblade_la_SOURCES += src/blade_session.c src/blade_protocol.c src/blade_space.c src/blade_method.c
libblade_la_SOURCES += src/blade_module_wss.c libblade_la_SOURCES += src/blade_module_wss.c src/blade_module_chat.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
......
...@@ -532,6 +532,7 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc) ...@@ -532,6 +532,7 @@ ks_status_t blade_connection_state_on_ready(blade_connection_t *bc)
if (callback) hook = callback(bc, BLADE_CONNECTION_STATE_CONDITION_POST); if (callback) hook = callback(bc, BLADE_CONNECTION_STATE_CONDITION_POST);
if (hook == BLADE_CONNECTION_STATE_HOOK_DISCONNECT) blade_connection_disconnect(bc); if (hook == BLADE_CONNECTION_STATE_HOOK_DISCONNECT) blade_connection_disconnect(bc);
else ks_sleep_ms(1);
return KS_STATUS_SUCCESS; return KS_STATUS_SUCCESS;
} }
......
/* /*
* Copyright (c) 2017, Shane Bryldt * 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
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of the original author; nor the names of any contributors * * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -78,6 +78,13 @@ KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP) ...@@ -78,6 +78,13 @@ KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP)
return KS_STATUS_SUCCESS; return KS_STATUS_SUCCESS;
} }
KS_DECLARE(blade_handle_t *) blade_module_handle_get(blade_module_t *bm)
{
ks_assert(bm);
return bm->handle;
}
KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm) KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm)
{ {
ks_assert(bm); ks_assert(bm);
...@@ -85,7 +92,7 @@ KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm) ...@@ -85,7 +92,7 @@ KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm)
return bm->module_data; return bm->module_data;
} }
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:
* mode:c * mode:c
......
差异被折叠。
...@@ -122,7 +122,7 @@ ks_status_t blade_transport_wss_init_create(blade_transport_wss_init_t **bt_wssi ...@@ -122,7 +122,7 @@ 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_request_handler(blade_module_t *bm, blade_request_t *breq);
ks_bool_t blade_test_echo_response_handler(blade_response_t *bres); ks_bool_t blade_test_echo_response_handler(blade_response_t *bres);
...@@ -427,7 +427,7 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_startup(blade_module_t *bm, config_s ...@@ -427,7 +427,7 @@ 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"); blade_space_create(&space, bm_wss->handle, bm, "blade.test");
ks_assert(space); ks_assert(space);
blade_method_create(&method, space, "echo", blade_test_echo_request_handler); blade_method_create(&method, space, "echo", blade_test_echo_request_handler);
...@@ -1248,9 +1248,10 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_c ...@@ -1248,9 +1248,10 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_inbound(blade_c
{ {
ks_assert(bc); ks_assert(bc);
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition); if (condition == BLADE_CONNECTION_STATE_CONDITION_PRE) {
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
}
ks_sleep_ms(1000);
return BLADE_CONNECTION_STATE_HOOK_SUCCESS; return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
} }
...@@ -1258,12 +1259,12 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_ ...@@ -1258,12 +1259,12 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_
{ {
ks_assert(bc); ks_assert(bc);
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
if (condition == BLADE_CONNECTION_STATE_CONDITION_PRE) { if (condition == BLADE_CONNECTION_STATE_CONDITION_PRE) {
blade_session_t *bs = NULL; blade_session_t *bs = NULL;
cJSON *req = NULL; cJSON *req = NULL;
ks_log(KS_LOG_DEBUG, "State Callback: %d\n", (int32_t)condition);
bs = blade_handle_sessions_get(blade_connection_handle_get(bc), blade_connection_session_get(bc)); bs = blade_handle_sessions_get(blade_connection_handle_get(bc), blade_connection_session_get(bc));
ks_assert(bs); ks_assert(bs);
...@@ -1273,17 +1274,17 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_ ...@@ -1273,17 +1274,17 @@ blade_connection_state_hook_t blade_transport_wss_on_state_ready_outbound(blade_
blade_session_read_unlock(bs); blade_session_read_unlock(bs);
} }
ks_sleep_ms(1000);
return BLADE_CONNECTION_STATE_HOOK_SUCCESS; return BLADE_CONNECTION_STATE_HOOK_SUCCESS;
} }
ks_bool_t blade_test_echo_request_handler(blade_request_t *breq) ks_bool_t blade_test_echo_request_handler(blade_module_t *bm, blade_request_t *breq)
{ {
blade_session_t *bs = NULL; blade_session_t *bs = NULL;
cJSON *res = NULL; cJSON *res = NULL;
ks_assert(bm);
ks_assert(breq); ks_assert(breq);
ks_log(KS_LOG_DEBUG, "Request Received!\n"); ks_log(KS_LOG_DEBUG, "Request Received!\n");
......
...@@ -55,7 +55,7 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, ...@@ -55,7 +55,7 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP,
breq->pool = pool; breq->pool = pool;
breq->session_id = ks_pstrdup(pool, session_id); breq->session_id = ks_pstrdup(pool, session_id);
breq->message = cJSON_Duplicate(json, 1); breq->message = cJSON_Duplicate(json, 1);
breq->message_id = cJSON_GetObjectCstr(json, "id"); breq->message_id = cJSON_GetObjectCstr(breq->message, "id");
breq->callback = callback; breq->callback = callback;
*breqP = breq; *breqP = breq;
...@@ -81,7 +81,11 @@ KS_DECLARE(ks_status_t) blade_request_destroy(blade_request_t **breqP) ...@@ -81,7 +81,11 @@ 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)
{ {
blade_response_t *bres = NULL; blade_response_t *bres = NULL;
ks_pool_t *pool = NULL; ks_pool_t *pool = NULL;
...@@ -125,6 +129,50 @@ KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP) ...@@ -125,6 +129,50 @@ 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_event_create(blade_event_t **bevP,
blade_handle_t *bh,
const char *session_id,
cJSON *json)
{
blade_event_t *bev = NULL;
ks_pool_t *pool = NULL;
ks_assert(bevP);
ks_assert(bh);
ks_assert(session_id);
ks_assert(json);
pool = blade_handle_pool_get(bh);
ks_assert(pool);
bev = ks_pool_alloc(pool, sizeof(blade_event_t));
bev->handle = bh;
bev->pool = pool;
bev->session_id = ks_pstrdup(pool, session_id);
bev->message = cJSON_Duplicate(json, 1);
*bevP = bev;
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_event_destroy(blade_event_t **bevP)
{
blade_event_t *bev = NULL;
ks_assert(bevP);
ks_assert(*bevP);
bev = *bevP;
ks_pool_free(bev->pool, (void **)&bev->session_id);
cJSON_Delete(bev->message);
ks_pool_free(bev->pool, bevP);
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) 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 *root = NULL;
...@@ -208,6 +256,35 @@ KS_DECLARE(ks_status_t) blade_rpc_error_create(ks_pool_t *pool, cJSON **json, cJ ...@@ -208,6 +256,35 @@ KS_DECLARE(ks_status_t) blade_rpc_error_create(ks_pool_t *pool, cJSON **json, cJ
return KS_STATUS_SUCCESS; return KS_STATUS_SUCCESS;
} }
KS_DECLARE(ks_status_t) blade_rpc_event_create(ks_pool_t *pool, cJSON **json, cJSON **result, const char *event)
{
cJSON *root = NULL;
cJSON *b = NULL;
cJSON *r = NULL;
ks_assert(pool);
ks_assert(json);
ks_assert(event);
root = cJSON_CreateObject();
cJSON_AddStringToObject(root, "jsonrpc", "2.0");
b = cJSON_CreateObject();
cJSON_AddStringToObject(b, "event", event);
cJSON_AddItemToObject(root, "blade", b);
if (result) {
r = cJSON_CreateObject();
cJSON_AddItemToObject(root, "result", r);
*result = r;
}
*json = root;
return KS_STATUS_SUCCESS;
}
/* For Emacs: /* For Emacs:
* Local Variables: * Local Variables:
* mode:c * mode:c
......
...@@ -36,13 +36,14 @@ ...@@ -36,13 +36,14 @@
struct blade_space_s { struct blade_space_s {
blade_handle_t *handle; blade_handle_t *handle;
ks_pool_t *pool; ks_pool_t *pool;
blade_module_t *module;
const char *path; const char *path;
ks_hash_t *methods; ks_hash_t *methods;
}; };
KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, const char *path) KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, blade_module_t *bm, const char *path)
{ {
blade_space_t *bs = NULL; blade_space_t *bs = NULL;
ks_pool_t *pool = NULL; ks_pool_t *pool = NULL;
...@@ -56,6 +57,7 @@ KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t * ...@@ -56,6 +57,7 @@ KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *
bs = ks_pool_alloc(pool, sizeof(blade_space_t)); bs = ks_pool_alloc(pool, sizeof(blade_space_t));
bs->handle = bh; bs->handle = bh;
bs->pool = pool; bs->pool = pool;
bs->module = bm;
bs->path = path; // @todo dup and keep copy? should mostly be literals 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_hash_create(&bs->methods, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bs->pool);
ks_assert(bs); ks_assert(bs);
...@@ -101,6 +103,13 @@ KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs) ...@@ -101,6 +103,13 @@ KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs)
return bs->handle; return bs->handle;
} }
KS_DECLARE(blade_module_t *) blade_space_module_get(blade_space_t *bs)
{
ks_assert(bs);
return bs->module;
}
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs) KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs)
{ {
ks_assert(bs); ks_assert(bs);
......
...@@ -49,14 +49,21 @@ struct blade_handle_s { ...@@ -49,14 +49,21 @@ struct blade_handle_s {
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 ks_hash_t *spaces; // registered method spaces exposed by modules
// registered event callback registry
// @todo should probably use a blade_handle_event_registration_t and contain optional userdata to pass from registration back into the callback, like
// a blade_module_t to get at inner module data for events that service modules may need to subscribe to between each other
ks_hash_t *events;
//blade_identity_t *identity; //blade_identity_t *identity;
blade_datastore_t *datastore; blade_datastore_t *datastore;
// @todo insert on connection creations, remove on connection destructions, key based on a UUID for the connection // @todo insert on connection creations, remove on connection destructions, key based on a UUID for the connection
ks_hash_t *connections; // active connections keyed by connection id ks_hash_t *connections; // active connections keyed by connection id
// @todo insert on session creations, remove on session destructions, key based on a UUID for the session // @todo insert on session creations, remove on session destructions, key based on a UUID for the session
ks_hash_t *sessions; // active sessions keyed by session id ks_hash_t *sessions; // active sessions keyed by session id
ks_hash_t *session_state_callbacks;
// @todo another hash with sessions keyed by the remote identity without parameters for quick lookup by target identity on sending? // @todo another hash with sessions keyed by the remote identity without parameters for quick lookup by target identity on sending?
ks_hash_t *requests; // outgoing requests waiting for a response keyed by the message id ks_hash_t *requests; // outgoing requests waiting for a response keyed by the message id
}; };
...@@ -70,7 +77,6 @@ struct blade_handle_transport_registration_s { ...@@ -70,7 +77,6 @@ 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,
...@@ -110,6 +116,59 @@ KS_DECLARE(ks_status_t) blade_handle_transport_registration_destroy(blade_handle ...@@ -110,6 +116,59 @@ KS_DECLARE(ks_status_t) blade_handle_transport_registration_destroy(blade_handle
} }
typedef struct blade_handle_session_state_callback_registration_s blade_handle_session_state_callback_registration_t;
struct blade_handle_session_state_callback_registration_s {
ks_pool_t *pool;
const char *id;
void *data;
blade_session_state_callback_t callback;
};
ks_status_t blade_handle_session_state_callback_registration_create(blade_handle_session_state_callback_registration_t **bhsscrP,
ks_pool_t *pool,
void *data,
blade_session_state_callback_t callback)
{
blade_handle_session_state_callback_registration_t *bhsscr = NULL;
uuid_t uuid;
ks_assert(bhsscrP);
ks_assert(pool);
ks_assert(callback);
ks_uuid(&uuid);
bhsscr = ks_pool_alloc(pool, sizeof(blade_handle_session_state_callback_registration_t));
bhsscr->pool = pool;
bhsscr->id = ks_uuid_str(pool, &uuid);
bhsscr->data = data;
bhsscr->callback = callback;
*bhsscrP = bhsscr;
return KS_STATUS_SUCCESS;
}
ks_status_t blade_handle_session_state_callback_registration_destroy(blade_handle_session_state_callback_registration_t **bhsscrP)
{
blade_handle_session_state_callback_registration_t *bhsscr = NULL;
ks_assert(bhsscrP);
bhsscr = *bhsscrP;
*bhsscrP = NULL;
ks_assert(bhsscr);
ks_pool_free(bhsscr->pool, &bhsscr->id);
ks_pool_free(bhsscr->pool, &bhsscr);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool, ks_thread_pool_t *tpool) KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *pool, ks_thread_pool_t *tpool)
{ {
...@@ -137,12 +196,17 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo ...@@ -137,12 +196,17 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo
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_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_assert(bh->spaces);
ks_hash_create(&bh->events, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->events);
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);
ks_hash_create(&bh->sessions, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool); ks_hash_create(&bh->sessions, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->sessions); ks_assert(bh->sessions);
// @todo decide if this is uint32_t or uuid string, prefer uuid string to avoid needing another lock and variable for next id ks_hash_create(&bh->session_state_callbacks, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->session_state_callbacks);
ks_hash_create(&bh->requests, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool); ks_hash_create(&bh->requests, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool);
ks_assert(bh->requests); ks_assert(bh->requests);
...@@ -172,8 +236,10 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP) ...@@ -172,8 +236,10 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP)
blade_handle_shutdown(bh); blade_handle_shutdown(bh);
ks_hash_destroy(&bh->requests); ks_hash_destroy(&bh->requests);
ks_hash_destroy(&bh->session_state_callbacks);
ks_hash_destroy(&bh->sessions); ks_hash_destroy(&bh->sessions);
ks_hash_destroy(&bh->connections); ks_hash_destroy(&bh->connections);
ks_hash_destroy(&bh->events);
ks_hash_destroy(&bh->spaces); ks_hash_destroy(&bh->spaces);
ks_hash_destroy(&bh->transports); ks_hash_destroy(&bh->transports);
...@@ -267,6 +333,14 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh) ...@@ -267,6 +333,14 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh)
// @todo call onshutdown and onunload callbacks for modules from DSOs, which will unregister transports and spaces, and will disconnect remaining // @todo call onshutdown and onunload callbacks for modules from DSOs, which will unregister transports and spaces, and will disconnect remaining
// unattached connections // unattached connections
for (it = ks_hash_first(bh->events, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
void *key = NULL;
blade_event_callback_t *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
blade_handle_event_unregister(bh, (const char *)key);
}
for (it = ks_hash_first(bh->spaces, KS_UNLOCKED); it; it = ks_hash_next(&it)) { for (it = ks_hash_first(bh->spaces, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
void *key = NULL; void *key = NULL;
blade_space_t *value = NULL; blade_space_t *value = NULL;
...@@ -409,6 +483,53 @@ KS_DECLARE(blade_space_t *) blade_handle_space_lookup(blade_handle_t *bh, const ...@@ -409,6 +483,53 @@ KS_DECLARE(blade_space_t *) blade_handle_space_lookup(blade_handle_t *bh, const
return bs; return bs;
} }
KS_DECLARE(ks_status_t) blade_handle_event_register(blade_handle_t *bh, const char *event, blade_event_callback_t callback)
{
ks_assert(bh);
ks_assert(event);
ks_assert(callback);
ks_hash_write_lock(bh->events);
ks_hash_insert(bh->events, (void *)event, (void *)(intptr_t)callback);
ks_hash_write_unlock(bh->events);
ks_log(KS_LOG_DEBUG, "Event Registered: %s\n", event);
return KS_STATUS_SUCCESS;
}
KS_DECLARE(ks_status_t) blade_handle_event_unregister(blade_handle_t *bh, const char *event)
{
ks_bool_t removed = KS_FALSE;
ks_assert(bh);
ks_assert(event);
ks_hash_write_lock(bh->events);
if (ks_hash_remove(bh->events, (void *)event)) removed = KS_TRUE;
ks_hash_write_unlock(bh->events);
if (removed) {
ks_log(KS_LOG_DEBUG, "Event Unregistered: %s\n", event);
}
return KS_STATUS_SUCCESS;
}
KS_DECLARE(blade_event_callback_t) blade_handle_event_lookup(blade_handle_t *bh, const char *event)
{
blade_event_callback_t callback = NULL;
ks_assert(bh);
ks_assert(event);
ks_hash_read_lock(bh->events);
callback = (blade_event_callback_t)(intptr_t)ks_hash_search(bh->events, (void *)event, KS_UNLOCKED);
ks_hash_read_unlock(bh->events);
return callback;
}
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;
...@@ -512,10 +633,11 @@ KS_DECLARE(ks_status_t) blade_handle_connections_remove(blade_connection_t *bc) ...@@ -512,10 +633,11 @@ KS_DECLARE(ks_status_t) blade_handle_connections_remove(blade_connection_t *bc)
blade_connection_write_unlock(bc); blade_connection_write_unlock(bc);
// @todo call bh->connection_callbacks
return ret; return ret;
} }
KS_DECLARE(blade_session_t *) blade_handle_sessions_get(blade_handle_t *bh, const char *sid) KS_DECLARE(blade_session_t *) blade_handle_sessions_get(blade_handle_t *bh, const char *sid)
{ {
blade_session_t *bs = NULL; blade_session_t *bs = NULL;
...@@ -569,6 +691,92 @@ KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs) ...@@ -569,6 +691,92 @@ KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs)
return ret; return ret;
} }
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions, const char *exclude, cJSON *json)
{
blade_session_t *bs = NULL;
ks_assert(bh);
ks_assert(sessions);
ks_assert(json);
list_iterator_start(sessions);
while (list_iterator_hasnext(sessions)) {
const char *sessionid = list_iterator_next(sessions);
if (exclude && !strcmp(exclude, sessionid)) continue;
bs = blade_handle_sessions_get(bh, sessionid);
if (!bs) {
ks_log(KS_LOG_DEBUG, "This should not happen\n");
continue;
}
blade_session_send(bs, json, NULL);
blade_session_read_unlock(bs);
}
list_iterator_stop(sessions);
}
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_register(blade_handle_t *bh, void *data, blade_session_state_callback_t callback, const char **id)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_handle_session_state_callback_registration_t *bhsscr = NULL;
ks_assert(bh);
ks_assert(callback);
ks_assert(id);
blade_handle_session_state_callback_registration_create(&bhsscr, blade_handle_pool_get(bh), data, callback);
ks_assert(bhsscr);
ks_hash_write_lock(bh->session_state_callbacks);
ret = ks_hash_insert(bh->session_state_callbacks, (void *)bhsscr->id, bhsscr);
ks_hash_write_unlock(bh->session_state_callbacks);
*id = bhsscr->id;
return ret;
}
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_unregister(blade_handle_t *bh, const char *id)
{
ks_status_t ret = KS_STATUS_SUCCESS;
blade_handle_session_state_callback_registration_t *bhsscr = NULL;
ks_assert(bh);
ks_assert(id);
ks_hash_write_lock(bh->session_state_callbacks);
bhsscr = (blade_handle_session_state_callback_registration_t *)ks_hash_remove(bh->session_state_callbacks, (void *)id);
if (!bhsscr) ret = KS_STATUS_FAIL;
ks_hash_write_lock(bh->session_state_callbacks);
if (bhsscr) blade_handle_session_state_callback_registration_destroy(&bhsscr);
return ret;
}
KS_DECLARE(void) blade_handle_session_state_callbacks_execute(blade_session_t *bs, blade_session_state_condition_t condition)
{
blade_handle_t *bh = NULL;
ks_hash_iterator_t *it = NULL;
ks_assert(bs);
if (blade_session_state_get(bs) == BLADE_SESSION_STATE_NONE) return;
bh = blade_session_handle_get(bs);
ks_assert(bh);
ks_hash_read_lock(bh->session_state_callbacks);
for (it = ks_hash_first(bh->session_state_callbacks, KS_UNLOCKED); it; it = ks_hash_next(&it)) {
void *key = NULL;
blade_handle_session_state_callback_registration_t *value = NULL;
ks_hash_this(it, (const void **)&key, NULL, (void **)&value);
value->callback(bs, condition, value->data);
}
ks_hash_read_unlock(bh->session_state_callbacks);
}
KS_DECLARE(blade_request_t *) blade_handle_requests_get(blade_handle_t *bh, const char *mid) KS_DECLARE(blade_request_t *) blade_handle_requests_get(blade_handle_t *bh, const char *mid)
{ {
......
/* /*
* Copyright (c) 2017, Shane Bryldt * 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
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* * Neither the name of the original author; nor the names of any contributors * * 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 * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
KS_BEGIN_EXTERN_C KS_BEGIN_EXTERN_C
KS_DECLARE(ks_status_t) blade_module_create(blade_module_t **bmP, blade_handle_t *bh, void *module_data, blade_module_callbacks_t *module_callbacks); KS_DECLARE(ks_status_t) blade_module_create(blade_module_t **bmP, blade_handle_t *bh, void *module_data, blade_module_callbacks_t *module_callbacks);
KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP); KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP);
KS_DECLARE(blade_handle_t *) blade_module_handle_get(blade_module_t *bm);
KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm); KS_DECLARE(void *) blade_module_data_get(blade_module_t *bm);
// @todo very temporary, this is just here to get the wss module loaded until DSO is in place // @todo very temporary, this is just here to get the wss module loaded until DSO is in place
...@@ -45,6 +46,11 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_load(blade_module_t **bmP, blade_han ...@@ -45,6 +46,11 @@ KS_DECLARE(ks_status_t) blade_module_wss_on_load(blade_module_t **bmP, blade_han
KS_DECLARE(ks_status_t) blade_module_wss_on_unload(blade_module_t *bm); KS_DECLARE(ks_status_t) blade_module_wss_on_unload(blade_module_t *bm);
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);
KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm); KS_DECLARE(ks_status_t) blade_module_wss_on_shutdown(blade_module_t *bm);
KS_DECLARE(ks_status_t) blade_module_chat_on_load(blade_module_t **bmP, blade_handle_t *bh);
KS_DECLARE(ks_status_t) blade_module_chat_on_unload(blade_module_t *bm);
KS_DECLARE(ks_status_t) blade_module_chat_on_startup(blade_module_t *bm, config_setting_t *config);
KS_DECLARE(ks_status_t) blade_module_chat_on_shutdown(blade_module_t *bm);
KS_END_EXTERN_C KS_END_EXTERN_C
#endif #endif
......
...@@ -44,9 +44,12 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, ...@@ -44,9 +44,12 @@ KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP,
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_event_create(blade_event_t **bevP, blade_handle_t *bh, const char *session_id, cJSON *json);
KS_DECLARE(ks_status_t) blade_event_destroy(blade_event_t **bevP);
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_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_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_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_DECLARE(ks_status_t) blade_rpc_event_create(ks_pool_t *pool, cJSON **json, cJSON **result, const char *event);
KS_END_EXTERN_C KS_END_EXTERN_C
#endif #endif
......
...@@ -41,12 +41,19 @@ KS_DECLARE(ks_status_t) blade_session_destroy(blade_session_t **bsP); ...@@ -41,12 +41,19 @@ KS_DECLARE(ks_status_t) blade_session_destroy(blade_session_t **bsP);
KS_DECLARE(ks_status_t) blade_session_startup(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_session_startup(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_shutdown(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_session_shutdown(blade_session_t *bs);
KS_DECLARE(blade_handle_t *) blade_session_handle_get(blade_session_t *bs); KS_DECLARE(blade_handle_t *) blade_session_handle_get(blade_session_t *bs);
KS_DECLARE(ks_pool_t *) blade_session_pool_get(blade_session_t *bs);
KS_DECLARE(const char *) blade_session_id_get(blade_session_t *bs); KS_DECLARE(const char *) blade_session_id_get(blade_session_t *bs);
KS_DECLARE(void) blade_session_id_set(blade_session_t *bs, const char *id); KS_DECLARE(void) blade_session_id_set(blade_session_t *bs, const char *id);
KS_DECLARE(blade_session_state_t) blade_session_state_get(blade_session_t *bs);
KS_DECLARE(cJSON *) blade_session_properties_get(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_read_lock(blade_session_t *bs, ks_bool_t block); KS_DECLARE(ks_status_t) blade_session_read_lock(blade_session_t *bs, ks_bool_t block);
KS_DECLARE(ks_status_t) blade_session_read_unlock(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_session_read_unlock(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_write_lock(blade_session_t *bs, ks_bool_t block); KS_DECLARE(ks_status_t) blade_session_write_lock(blade_session_t *bs, ks_bool_t block);
KS_DECLARE(ks_status_t) blade_session_write_unlock(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_session_write_unlock(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_properties_read_lock(blade_session_t *bs, ks_bool_t block);
KS_DECLARE(ks_status_t) blade_session_properties_read_unlock(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_session_properties_write_lock(blade_session_t *bs, ks_bool_t block);
KS_DECLARE(ks_status_t) blade_session_properties_write_unlock(blade_session_t *bs);
KS_DECLARE(void) blade_session_state_set(blade_session_t *bs, blade_session_state_t state); KS_DECLARE(void) blade_session_state_set(blade_session_t *bs, blade_session_state_t state);
KS_DECLARE(void) blade_session_hangup(blade_session_t *bs); 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);
......
...@@ -36,9 +36,10 @@ ...@@ -36,9 +36,10 @@
#include <blade.h> #include <blade.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); KS_DECLARE(ks_status_t) blade_space_create(blade_space_t **bsP, blade_handle_t *bh, blade_module_t *bm, const char *path);
KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP); KS_DECLARE(ks_status_t) blade_space_destroy(blade_space_t **bsP);
KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs); KS_DECLARE(blade_handle_t *) blade_space_handle_get(blade_space_t *bs);
KS_DECLARE(blade_module_t *) blade_space_module_get(blade_space_t *bs);
KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs); KS_DECLARE(const char *) blade_space_path_get(blade_space_t *bs);
KS_DECLARE(ks_status_t) blade_space_methods_add(blade_space_t *bs, blade_method_t *bm); KS_DECLARE(ks_status_t) blade_space_methods_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(ks_status_t) blade_space_methods_remove(blade_space_t *bs, blade_method_t *bm);
......
...@@ -55,6 +55,10 @@ KS_DECLARE(ks_status_t) blade_handle_space_register(blade_space_t *bs); ...@@ -55,6 +55,10 @@ 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(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(blade_space_t *) blade_handle_space_lookup(blade_handle_t *bh, const char *path);
KS_DECLARE(ks_status_t) blade_handle_event_register(blade_handle_t *bh, const char *event, blade_event_callback_t callback);
KS_DECLARE(ks_status_t) blade_handle_event_unregister(blade_handle_t *bh, const char *event);
KS_DECLARE(blade_event_callback_t) blade_handle_event_lookup(blade_handle_t *bh, const char *event);
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);
...@@ -64,6 +68,10 @@ KS_DECLARE(ks_status_t) blade_handle_connections_remove(blade_connection_t *bc); ...@@ -64,6 +68,10 @@ KS_DECLARE(ks_status_t) blade_handle_connections_remove(blade_connection_t *bc);
KS_DECLARE(blade_session_t *) blade_handle_sessions_get(blade_handle_t *bh, const char *sid); KS_DECLARE(blade_session_t *) blade_handle_sessions_get(blade_handle_t *bh, const char *sid);
KS_DECLARE(ks_status_t) blade_handle_sessions_add(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_handle_sessions_add(blade_session_t *bs);
KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs); KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs);
KS_DECLARE(void) blade_handle_sessions_send(blade_handle_t *bh, list_t *sessions, const char *exclude, cJSON *json);
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_register(blade_handle_t *bh, void *data, blade_session_state_callback_t callback, const char **id);
KS_DECLARE(ks_status_t) blade_handle_session_state_callback_unregister(blade_handle_t *bh, const char *id);
KS_DECLARE(void) blade_handle_session_state_callbacks_execute(blade_session_t *bs, blade_session_state_condition_t condition);
KS_DECLARE(blade_request_t *) blade_handle_requests_get(blade_handle_t *bh, const char *mid); KS_DECLARE(blade_request_t *) blade_handle_requests_get(blade_handle_t *bh, const char *mid);
KS_DECLARE(ks_status_t) blade_handle_requests_add(blade_request_t *br); KS_DECLARE(ks_status_t) blade_handle_requests_add(blade_request_t *br);
......
...@@ -43,21 +43,24 @@ typedef struct blade_identity_s blade_identity_t; ...@@ -43,21 +43,24 @@ typedef struct blade_identity_s blade_identity_t;
typedef struct blade_module_s blade_module_t; typedef struct blade_module_s blade_module_t;
typedef struct blade_module_callbacks_s blade_module_callbacks_t; typedef struct blade_module_callbacks_s blade_module_callbacks_t;
typedef struct blade_transport_callbacks_s blade_transport_callbacks_t; typedef struct blade_transport_callbacks_s blade_transport_callbacks_t;
typedef struct blade_session_callbacks_s blade_session_callbacks_t;
typedef struct blade_connection_s blade_connection_t; 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_event_s blade_event_t;
typedef struct blade_space_s blade_space_t; typedef struct blade_space_s blade_space_t;
typedef struct blade_method_s blade_method_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;
typedef ks_bool_t (*blade_datastore_fetch_callback_t)(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata);
typedef ks_bool_t (*blade_request_callback_t)(blade_module_t *bm, blade_request_t *breq);
typedef ks_bool_t (*blade_response_callback_t)(blade_response_t *bres);
typedef ks_bool_t (*blade_event_callback_t)(blade_event_t *bev);
typedef ks_bool_t (*blade_datastore_fetch_callback_t)(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata);
typedef enum { typedef enum {
...@@ -94,6 +97,11 @@ typedef enum { ...@@ -94,6 +97,11 @@ typedef enum {
} blade_connection_rank_t; } blade_connection_rank_t;
typedef enum {
BLADE_SESSION_STATE_CONDITION_PRE,
BLADE_SESSION_STATE_CONDITION_POST,
} blade_session_state_condition_t;
typedef enum { typedef enum {
BLADE_SESSION_STATE_NONE, BLADE_SESSION_STATE_NONE,
BLADE_SESSION_STATE_DESTROY, BLADE_SESSION_STATE_DESTROY,
...@@ -145,6 +153,8 @@ struct blade_transport_callbacks_s { ...@@ -145,6 +153,8 @@ struct blade_transport_callbacks_s {
blade_transport_state_callback_t onstate_ready_outbound; blade_transport_state_callback_t onstate_ready_outbound;
}; };
typedef void (*blade_session_state_callback_t)(blade_session_t *bs, blade_session_state_condition_t condition, void *data);
struct blade_request_s { struct blade_request_s {
blade_handle_t *handle; blade_handle_t *handle;
...@@ -167,6 +177,14 @@ struct blade_response_s { ...@@ -167,6 +177,14 @@ struct blade_response_s {
cJSON *message; cJSON *message;
}; };
struct blade_event_s {
blade_handle_t *handle;
ks_pool_t *pool;
const char *session_id;
cJSON *message;
};
KS_END_EXTERN_C KS_END_EXTERN_C
#endif #endif
......
...@@ -13,6 +13,11 @@ bladec_SOURCES = bladec.c tap.c ...@@ -13,6 +13,11 @@ bladec_SOURCES = bladec.c tap.c
bladec_CFLAGS = $(AM_CFLAGS) bladec_CFLAGS = $(AM_CFLAGS)
bladec_LDADD = $(TEST_LDADD) bladec_LDADD = $(TEST_LDADD)
check_PROGRAMS += blades
blades_SOURCES = blades.c tap.c
blades_CFLAGS = $(AM_CFLAGS)
blades_LDADD = $(TEST_LDADD)
TESTS=$(check_PROGRAMS) TESTS=$(check_PROGRAMS)
......
...@@ -26,22 +26,22 @@ struct command_def_s { ...@@ -26,22 +26,22 @@ struct command_def_s {
command_callback callback; command_callback callback;
}; };
void command_test(blade_handle_t *bh, char *args);
void command_quit(blade_handle_t *bh, char *args); void command_quit(blade_handle_t *bh, char *args);
void command_store(blade_handle_t *bh, char *args);
void command_fetch(blade_handle_t *bh, char *args);
void command_connect(blade_handle_t *bh, char *args); void command_connect(blade_handle_t *bh, char *args);
void command_chat(blade_handle_t *bh, char *args);
static const struct command_def_s command_defs[] = { static const struct command_def_s command_defs[] = {
{ "test", command_test },
{ "quit", command_quit }, { "quit", command_quit },
{ "store", command_store },
{ "fetch", command_fetch },
{ "connect", command_connect }, { "connect", command_connect },
{ "chat", command_chat },
{ NULL, NULL } { NULL, NULL }
}; };
ks_bool_t on_blade_chat_join_response(blade_response_t *bres);
ks_bool_t on_blade_chat_message_event(blade_event_t *bev);
void on_blade_session_state_callback(blade_session_t *bs, blade_session_state_condition_t condition, void *data);
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
blade_handle_t *bh = NULL; blade_handle_t *bh = NULL;
...@@ -50,16 +50,16 @@ int main(int argc, char **argv) ...@@ -50,16 +50,16 @@ int main(int argc, char **argv)
blade_module_t *mod_wss = NULL; blade_module_t *mod_wss = NULL;
//blade_identity_t *id = NULL; //blade_identity_t *id = NULL;
const char *cfgpath = "bladec.cfg"; const char *cfgpath = "bladec.cfg";
const char *session_state_callback_id = NULL;
ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG); ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG);
blade_init(); blade_init();
blade_handle_create(&bh, NULL, NULL); blade_handle_create(&bh, NULL, NULL);
if (argc > 1) cfgpath = argv[1]; if (argc > 1) cfgpath = argv[1];
config_init(&config); config_init(&config);
if (!config_read_file(&config, cfgpath)) { if (!config_read_file(&config, cfgpath)) {
ks_log(KS_LOG_ERROR, "%s:%d - %s\n", config_error_file(&config), config_error_line(&config), config_error_text(&config)); ks_log(KS_LOG_ERROR, "%s:%d - %s\n", config_error_file(&config), config_error_line(&config), config_error_text(&config));
...@@ -76,7 +76,7 @@ int main(int argc, char **argv) ...@@ -76,7 +76,7 @@ int main(int argc, char **argv)
ks_log(KS_LOG_ERROR, "The 'blade' config setting is not a group\n"); ks_log(KS_LOG_ERROR, "The 'blade' config setting is not a group\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (blade_handle_startup(bh, config_blade) != KS_STATUS_SUCCESS) { if (blade_handle_startup(bh, config_blade) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_ERROR, "Blade startup failed\n"); ks_log(KS_LOG_ERROR, "Blade startup failed\n");
return EXIT_FAILURE; return EXIT_FAILURE;
...@@ -91,8 +91,13 @@ int main(int argc, char **argv) ...@@ -91,8 +91,13 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
blade_handle_event_register(bh, "blade.chat.message", on_blade_chat_message_event);
blade_handle_session_state_callback_register(bh, NULL, on_blade_session_state_callback, &session_state_callback_id);
loop(bh); loop(bh);
blade_handle_session_state_callback_unregister(bh, session_state_callback_id);
blade_module_wss_on_shutdown(mod_wss); blade_module_wss_on_shutdown(mod_wss);
blade_module_wss_on_unload(mod_wss); blade_module_wss_on_unload(mod_wss);
...@@ -104,7 +109,37 @@ int main(int argc, char **argv) ...@@ -104,7 +109,37 @@ int main(int argc, char **argv)
return 0; return 0;
} }
ks_bool_t on_blade_chat_message_event(blade_event_t *bev)
{
cJSON *res = NULL;
const char *from = NULL;
const char *message = NULL;
ks_assert(bev);
res = cJSON_GetObjectItem(bev->message, "result");
from = cJSON_GetObjectCstr(res, "from");
message = cJSON_GetObjectCstr(res, "message");
ks_log(KS_LOG_DEBUG, "Received Chat Message Event: (%s) %s\n", from, message);
return KS_FALSE;
}
void on_blade_session_state_callback(blade_session_t *bs, blade_session_state_condition_t condition, void *data)
{
blade_session_state_t state = blade_session_state_get(bs);
if (condition == BLADE_SESSION_STATE_CONDITION_PRE) {
ks_log(KS_LOG_DEBUG, "Blade Session State Changed: %s, %d\n", blade_session_id_get(bs), state);
if (state == BLADE_SESSION_STATE_READY) {
cJSON *req = NULL;
blade_rpc_request_create(blade_session_pool_get(bs), &req, NULL, NULL, "blade.chat.join");
blade_session_send(bs, req, on_blade_chat_join_response);
cJSON_Delete(req);
}
}
}
void buffer_console_input(void) void buffer_console_input(void)
{ {
...@@ -162,7 +197,7 @@ void loop(blade_handle_t *bh) ...@@ -162,7 +197,7 @@ void loop(blade_handle_t *bh)
void parse_argument(char **input, char **arg, char terminator) void parse_argument(char **input, char **arg, char terminator)
{ {
char *tmp; char *tmp;
ks_assert(input); ks_assert(input);
ks_assert(*input); ks_assert(*input);
ks_assert(arg); ks_assert(arg);
...@@ -183,11 +218,11 @@ void process_console_input(blade_handle_t *bh, char *line) ...@@ -183,11 +218,11 @@ void process_console_input(blade_handle_t *bh, char *line)
char *args = line; char *args = line;
char *cmd = NULL; char *cmd = NULL;
ks_bool_t found = KS_FALSE; ks_bool_t found = KS_FALSE;
ks_log(KS_LOG_DEBUG, "Output: %s\n", line); ks_log(KS_LOG_DEBUG, "Output: %s\n", line);
parse_argument(&args, &cmd, ' '); parse_argument(&args, &cmd, ' ');
ks_log(KS_LOG_DEBUG, "Command: %s, Args: %s\n", cmd, args); ks_log(KS_LOG_DEBUG, "Command: %s, Args: %s\n", cmd, args);
for (int32_t index = 0; command_defs[index].cmd; ++index) { for (int32_t index = 0; command_defs[index].cmd; ++index) {
...@@ -199,61 +234,78 @@ void process_console_input(blade_handle_t *bh, char *line) ...@@ -199,61 +234,78 @@ void process_console_input(blade_handle_t *bh, char *line)
if (!found) ks_log(KS_LOG_INFO, "Command '%s' unknown.\n", cmd); if (!found) ks_log(KS_LOG_INFO, "Command '%s' unknown.\n", cmd);
} }
void command_test(blade_handle_t *bh, char *args)
{
ks_log(KS_LOG_DEBUG, "Hello World!\n");
}
void command_quit(blade_handle_t *bh, char *args) void command_quit(blade_handle_t *bh, char *args)
{ {
ks_assert(bh); ks_assert(bh);
ks_assert(args); ks_assert(args);
ks_log(KS_LOG_DEBUG, "Shutting down\n"); ks_log(KS_LOG_DEBUG, "Shutting down\n");
g_shutdown = KS_TRUE; g_shutdown = KS_TRUE;
} }
void command_store(blade_handle_t *bh, char *args) void command_connect(blade_handle_t *bh, char *args)
{ {
char *key; blade_connection_t *bc = NULL;
char *data; blade_identity_t *target = NULL;
ks_assert(bh);
ks_assert(args); ks_assert(args);
parse_argument(&args, &key, ' '); blade_identity_create(&target, blade_handle_pool_get(bh));
parse_argument(&args, &data, ' ');
if (blade_identity_parse(target, args) == KS_STATUS_SUCCESS) blade_handle_connect(bh, &bc, target, NULL);
blade_handle_datastore_store(bh, key, strlen(key), data, strlen(data) + 1); blade_identity_destroy(&target);
} }
ks_bool_t blade_datastore_fetch_callback(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata) ks_bool_t on_blade_chat_join_response(blade_response_t *bres) // @todo this should get userdata passed in from when the callback is registered
{ {
ks_log(KS_LOG_INFO, "%s\n", data); ks_log(KS_LOG_DEBUG, "Received Chat Join Response!\n");
return KS_TRUE; return KS_FALSE;
} }
void command_fetch(blade_handle_t *bh, char *args) ks_bool_t on_blade_chat_send_response(blade_response_t *bres) // @todo this should get userdata passed in from when the callback is registered
{ {
char *key; ks_log(KS_LOG_DEBUG, "Received Chat Send Response!\n");
return KS_FALSE;
ks_assert(args);
parse_argument(&args, &key, ' ');
blade_handle_datastore_fetch(bh, blade_datastore_fetch_callback, key, strlen(key), bh);
} }
void command_connect(blade_handle_t *bh, char *args) void command_chat(blade_handle_t *bh, char *args)
{ {
blade_connection_t *bc = NULL; char *cmd = NULL;
blade_identity_t *target = NULL;
ks_assert(bh); ks_assert(bh);
ks_assert(args); ks_assert(args);
blade_identity_create(&target, blade_handle_pool_get(bh)); parse_argument(&args, &cmd, ' ');
ks_log(KS_LOG_DEBUG, "Chat Command: %s, Args: %s\n", cmd, args);
if (blade_identity_parse(target, args) == KS_STATUS_SUCCESS) blade_handle_connect(bh, &bc, target, NULL);
blade_identity_destroy(&target); if (!strcmp(cmd, "leave")) {
} else if (!strcmp(cmd, "send")) {
char *sid = NULL;
blade_session_t *bs = NULL;
cJSON *req = NULL;
cJSON *params = NULL;
parse_argument(&args, &sid, ' ');
bs = blade_handle_sessions_get(bh, sid);
if (!bs) {
ks_log(KS_LOG_DEBUG, "Unknown Session: %s\n", sid);
return;
}
blade_rpc_request_create(blade_handle_pool_get(bh), &req, &params, NULL, "blade.chat.send");
ks_assert(req);
ks_assert(params);
cJSON_AddStringToObject(params, "message", args);
blade_session_send(bs, req, on_blade_chat_send_response);
blade_session_read_unlock(bs);
cJSON_Delete(req);
} else {
ks_log(KS_LOG_DEBUG, "Unknown Chat Command: %s\n", cmd);
}
} }
blade: blade:
{ {
identity = "directory@domain"; identity = "peer@domain";
directory:
{
};
datastore: datastore:
{ {
database: database:
...@@ -11,18 +8,4 @@ blade: ...@@ -11,18 +8,4 @@ blade:
path = ":mem:"; path = ":mem:";
}; };
}; };
wss:
{
endpoints:
{
ipv4 = ( { address = "0.0.0.0", port = 2100 } );
ipv6 = ( { address = "::", port = 2100 } );
backlog = 128;
};
# SSL group is optional, disabled when absent
ssl:
{
# todo: server SSL stuffs here
};
};
}; };
blade:
{
identity = "peer@domain";
datastore:
{
database:
{
path = ":mem:";
};
};
};
#include "blade.h"
#include "tap.h"
#ifdef _WIN32
#define STDIO_FD(_fs) _fileno(_fs)
#define READ(_fd, _buffer, _count) _read(_fd, _buffer, _count)
#else
#define STDIO_FD(_fs) fileno(_fs)
#define READ(_fd, _buffer, _count) read(_fd, _buffer, _count)
#endif
#define CONSOLE_INPUT_MAX 512
ks_bool_t g_shutdown = KS_FALSE;
char g_console_input[CONSOLE_INPUT_MAX];
size_t g_console_input_length = 0;
size_t g_console_input_eol = 0;
void loop(blade_handle_t *bh);
void process_console_input(blade_handle_t *bh, char *line);
typedef void (*command_callback)(blade_handle_t *bh, char *args);
struct command_def_s {
const char *cmd;
command_callback callback;
};
void command_quit(blade_handle_t *bh, char *args);
static const struct command_def_s command_defs[] = {
{ "quit", command_quit },
{ NULL, NULL }
};
int main(int argc, char **argv)
{
blade_handle_t *bh = NULL;
config_t config;
config_setting_t *config_blade = NULL;
blade_module_t *mod_wss = NULL;
blade_module_t *mod_chat = NULL;
//blade_identity_t *id = NULL;
const char *cfgpath = "blades.cfg";
ks_global_set_default_logger(KS_LOG_LEVEL_DEBUG);
blade_init();
blade_handle_create(&bh, NULL, NULL);
if (argc > 1) cfgpath = argv[1];
config_init(&config);
if (!config_read_file(&config, cfgpath)) {
ks_log(KS_LOG_ERROR, "%s:%d - %s\n", config_error_file(&config), config_error_line(&config), config_error_text(&config));
config_destroy(&config);
return EXIT_FAILURE;
}
config_blade = config_lookup(&config, "blade");
if (!config_blade) {
ks_log(KS_LOG_ERROR, "Missing 'blade' config group\n");
config_destroy(&config);
return EXIT_FAILURE;
}
if (config_setting_type(config_blade) != CONFIG_TYPE_GROUP) {
ks_log(KS_LOG_ERROR, "The 'blade' config setting is not a group\n");
return EXIT_FAILURE;
}
if (blade_handle_startup(bh, config_blade) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_ERROR, "Blade startup failed\n");
return EXIT_FAILURE;
}
if (blade_module_wss_on_load(&mod_wss, bh) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_ERROR, "Blade WSS module load failed\n");
return EXIT_FAILURE;
}
if (blade_module_wss_on_startup(mod_wss, config_blade) != KS_STATUS_SUCCESS) {
ks_log(KS_LOG_ERROR, "Blade WSS module startup failed\n");
return EXIT_FAILURE;
}
blade_module_chat_on_load(&mod_chat, bh);
blade_module_chat_on_startup(mod_chat, config_blade);
loop(bh);
blade_module_chat_on_shutdown(mod_chat);
blade_module_chat_on_unload(mod_chat);
blade_module_wss_on_shutdown(mod_wss);
blade_module_wss_on_unload(mod_wss);
blade_handle_destroy(&bh);
blade_shutdown();
return 0;
}
void buffer_console_input(void)
{
ssize_t bytes = 0;
struct pollfd poll[1];
poll[0].fd = STDIO_FD(stdin);
poll[0].events = POLLIN | POLLERR;
if (ks_poll(poll, 1, 1) > 0) {
if (poll[0].revents & POLLIN) {
if ((bytes = READ(poll[0].fd, g_console_input + g_console_input_length, CONSOLE_INPUT_MAX - g_console_input_length)) <= 0) {
// @todo error
return;
}
g_console_input_length += bytes;
}
}
}
void loop(blade_handle_t *bh)
{
while (!g_shutdown) {
ks_bool_t eol = KS_FALSE;
buffer_console_input();
for (; g_console_input_eol < g_console_input_length; ++g_console_input_eol) {
char c = g_console_input[g_console_input_eol];
if (c == '\r' || c == '\n') {
eol = KS_TRUE;
break;
}
}
if (eol) {
g_console_input[g_console_input_eol] = '\0';
process_console_input(bh, g_console_input);
g_console_input_eol++;
for (; g_console_input_eol < g_console_input_length; ++g_console_input_eol) {
char c = g_console_input[g_console_input_eol];
if (c != '\r' && c != '\n') break;
}
if (g_console_input_eol == g_console_input_length) g_console_input_eol = g_console_input_length = 0;
else {
memcpy(g_console_input, g_console_input + g_console_input_eol, g_console_input_length - g_console_input_eol);
g_console_input_length -= g_console_input_eol;
g_console_input_eol = 0;
}
}
if (g_console_input_length == CONSOLE_INPUT_MAX) {
// @todo lines must not exceed 512 bytes, treat as error and ignore buffer until next new line?
ks_assert(0);
}
}
}
void parse_argument(char **input, char **arg, char terminator)
{
char *tmp;
ks_assert(input);
ks_assert(*input);
ks_assert(arg);
tmp = *input;
*arg = tmp;
while (*tmp && *tmp != terminator) ++tmp;
if (*tmp == terminator) {
*tmp = '\0';
++tmp;
}
*input = tmp;
}
void process_console_input(blade_handle_t *bh, char *line)
{
char *args = line;
char *cmd = NULL;
ks_bool_t found = KS_FALSE;
ks_log(KS_LOG_DEBUG, "Output: %s\n", line);
parse_argument(&args, &cmd, ' ');
ks_log(KS_LOG_DEBUG, "Command: %s, Args: %s\n", cmd, args);
for (int32_t index = 0; command_defs[index].cmd; ++index) {
if (!strcmp(command_defs[index].cmd, cmd)) {
found = KS_TRUE;
command_defs[index].callback(bh, args);
}
}
if (!found) ks_log(KS_LOG_INFO, "Command '%s' unknown.\n", cmd);
}
void command_quit(blade_handle_t *bh, char *args)
{
ks_assert(bh);
ks_assert(args);
ks_log(KS_LOG_DEBUG, "Shutting down\n");
g_shutdown = KS_TRUE;
}
blade:
{
identity = "service@domain";
directory:
{
};
datastore:
{
database:
{
path = ":mem:";
};
};
wss:
{
endpoints:
{
ipv4 = ( { address = "0.0.0.0", port = 2100 } );
ipv6 = ( { address = "::", port = 2100 } );
backlog = 128;
};
# SSL group is optional, disabled when absent
ssl:
{
# todo: server SSL stuffs here
};
};
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论