diff --git a/libs/libblade/src/blade_protocol.c b/libs/libblade/src/blade_protocol.c index 4a3c071594..830be262f0 100644 --- a/libs/libblade/src/blade_protocol.c +++ b/libs/libblade/src/blade_protocol.c @@ -1,23 +1,23 @@ /* * Copyright (c) 2017, Shane Bryldt * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,22 +33,26 @@ #include "blade.h" -KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, ks_pool_t *pool, const char *session_id, cJSON *json /*, response_callback*/) +KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, blade_handle_t *bh, const char *session_id, cJSON *json) { blade_request_t *breq = NULL; + ks_pool_t *pool = NULL; ks_assert(breqP); - ks_assert(pool); + ks_assert(bh); ks_assert(session_id); ks_assert(json); + pool = blade_handle_pool_get(bh); + ks_assert(pool); + breq = ks_pool_alloc(pool, sizeof(blade_request_t)); + breq->handle = bh; breq->pool = pool; - breq->refs = 1; breq->session_id = ks_pstrdup(pool, session_id); breq->message = json; breq->message_id = cJSON_GetObjectCstr(json, "id"); - //breq->response_callback = response_callback; + *breqP = breq; return KS_STATUS_SUCCESS; @@ -72,6 +76,51 @@ 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) +{ + blade_response_t *bres = NULL; + ks_pool_t *pool = NULL; + + ks_assert(bresP); + ks_assert(bh); + ks_assert(session_id); + ks_assert(breq); + ks_assert(json); + + pool = blade_handle_pool_get(bh); + ks_assert(pool); + + bres = ks_pool_alloc(pool, sizeof(blade_response_t)); + bres->handle = bh; + bres->pool = pool; + bres->session_id = ks_pstrdup(pool, session_id); + bres->request = breq; + bres->message = json; + + *bresP = bres; + + return KS_STATUS_SUCCESS; +} + +KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP) +{ + blade_response_t *bres = NULL; + + ks_assert(bresP); + ks_assert(*bresP); + + bres = *bresP; + + ks_pool_free(bres->pool, (void **)&bres->session_id); + blade_request_destroy(&bres->request); + cJSON_Delete(bres->message); + + ks_pool_free(bres->pool, bresP); + + return KS_STATUS_SUCCESS; +} + + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/libblade/src/blade_session.c b/libs/libblade/src/blade_session.c index d5037bfcad..58c9b323d1 100644 --- a/libs/libblade/src/blade_session.c +++ b/libs/libblade/src/blade_session.c @@ -485,11 +485,20 @@ 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) { + blade_request_t *request = NULL; + const char *method = NULL; + ks_assert(bs); ks_assert(json); - // @todo check json for "method", if this is an outgoing request then build up the data for a response to lookup the message id and get back to the request - // this can reuse blade_request_t so that when the blade_response_t is passed up the blade_request_t within it is familiar from inbound requests + method = cJSON_GetObjectCstr(json, "method"); + if (method) { + blade_request_create(&request, bs->handle, bs->id, json); + ks_assert(request); + + // @todo set request TTL and figure out when requests are checked for expiration (separate thread in the handle?) + blade_handle_requests_add(request); + } if (list_empty(&bs->connections)) { // @todo cache the blade_request_t here if it exists to gaurentee it's cached before a response could be received @@ -508,6 +517,11 @@ KS_DECLARE(ks_status_t) blade_session_send(blade_session_t *bs, cJSON *json) ks_status_t blade_session_process(blade_session_t *bs, cJSON *json) { ks_status_t ret = KS_STATUS_SUCCESS; + blade_request_t *breq = NULL; + blade_response_t *bres = NULL; + const char *jsonrpc = NULL; + const char *id = NULL; + const char *method = NULL; ks_assert(bs); ks_assert(json); @@ -515,6 +529,50 @@ ks_status_t blade_session_process(blade_session_t *bs, cJSON *json) ks_log(KS_LOG_DEBUG, "Session (%s) processing\n", bs->id); // @todo teardown the message, convert into a blade_request_t or blade_response_t + // @todo validate the jsonrpc fields + + jsonrpc = cJSON_GetObjectCstr(json, "jsonrpc"); + if (!jsonrpc || strcmp(jsonrpc, "2.0")) { + ks_log(KS_LOG_DEBUG, "Received message is not the expected protocol\n"); + // @todo send error response, code = -32600 (invalid request) + // @todo hangup session entirely? + return KS_STATUS_FAIL; + } + + id = cJSON_GetObjectCstr(json, "id"); + if (!id) { + ks_log(KS_LOG_DEBUG, "Received message is missing 'id'\n"); + // @todo send error response, code = -32600 (invalid request) + // @todo hangup session entirely? + return KS_STATUS_FAIL; + } + + method = cJSON_GetObjectCstr(json, "method"); + if (method) { + // @todo use method to find RPC callbacks + + blade_request_create(&breq, bs->handle, bs->id, json); + ks_assert(breq); + + // @todo call request callback handler + } else { + breq = blade_handle_requests_get(bs->handle, id); + if (!breq) { + // @todo hangup session entirely? + return KS_STATUS_FAIL; + } + blade_handle_requests_remove(breq); + + method = cJSON_GetObjectCstr(breq->message, "method"); + ks_assert(method); + + // @todo use method to find RPC callbacks + + blade_response_create(&bres, bs->handle, bs->id, breq, json); + ks_assert(bres); + + // @todo call response callback handler + } return ret; } diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c index 1a680a0ff5..56357344ce 100644 --- a/libs/libblade/src/blade_stack.c +++ b/libs/libblade/src/blade_stack.c @@ -1,23 +1,23 @@ /* * Copyright (c) 2007-2014, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -43,7 +43,7 @@ struct blade_handle_s { bhpvt_flag_t flags; ks_pool_t *pool; ks_thread_pool_t *tpool; - + config_setting_t *config_directory; config_setting_t *config_datastore; @@ -125,7 +125,7 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo ks_thread_pool_create(&tpool, BLADE_HANDLE_TPOOL_MIN, BLADE_HANDLE_TPOOL_MAX, BLADE_HANDLE_TPOOL_STACK, KS_PRI_NORMAL, BLADE_HANDLE_TPOOL_IDLE); ks_assert(tpool); } - + bh = ks_pool_alloc(pool, sizeof(blade_handle_t)); bh->flags = newflags; bh->pool = pool; @@ -133,7 +133,7 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo ks_hash_create(&bh->transports, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool); ks_assert(bh->transports); - + ks_hash_create(&bh->connections, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool); 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); @@ -141,7 +141,7 @@ KS_DECLARE(ks_status_t) blade_handle_create(blade_handle_t **bhP, ks_pool_t *poo // @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->requests, KS_HASH_MODE_CASE_INSENSITIVE, KS_HASH_FLAG_NOLOCK | KS_HASH_FLAG_DUP_CHECK, bh->pool); ks_assert(bh->requests); - + *bhP = bh; return KS_STATUS_SUCCESS; @@ -185,21 +185,21 @@ ks_status_t blade_handle_config(blade_handle_t *bh, config_setting_t *config) { config_setting_t *directory = NULL; config_setting_t *datastore = NULL; - + ks_assert(bh); if (!config) return KS_STATUS_FAIL; if (!config_setting_is_group(config)) return KS_STATUS_FAIL; directory = config_setting_get_member(config, "directory"); - + datastore = config_setting_get_member(config, "datastore"); //if (datastore && !config_setting_is_group(datastore)) return KS_STATUS_FAIL; bh->config_directory = directory; bh->config_datastore = datastore; - + return KS_STATUS_SUCCESS; } @@ -222,7 +222,7 @@ KS_DECLARE(ks_status_t) blade_handle_startup(blade_handle_t *bh, config_setting_ } // @todo load DSOs - + // @todo call onload and onstartup callbacks for modules from DSOs return KS_STATUS_SUCCESS; @@ -237,20 +237,20 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh) for (it = ks_hash_first(bh->requests, KS_UNLOCKED); it; it = ks_hash_next(&it)) { void *key = NULL; blade_request_t *value = NULL; - + ks_hash_this(it, (const void **)&key, NULL, (void **)&value); ks_hash_remove(bh->requests, key); - + blade_request_destroy(&value); } - + for (it = ks_hash_first(bh->sessions, KS_UNLOCKED); it; it = ks_hash_next(&it)) { void *key = NULL; blade_session_t *value = NULL; - + ks_hash_this(it, (const void **)&key, NULL, (void **)&value); ks_hash_remove(bh->requests, key); - + blade_session_hangup(value); } while (ks_hash_count(bh->sessions) > 0) ks_sleep_ms(100); @@ -280,7 +280,7 @@ KS_DECLARE(ks_status_t) blade_handle_transport_register(blade_handle_t *bh, blad { blade_handle_transport_registration_t *bhtr = NULL; blade_handle_transport_registration_t *bhtr_old = NULL; - + ks_assert(bh); ks_assert(bm); ks_assert(name); @@ -326,7 +326,7 @@ KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connectio ks_status_t ret = KS_STATUS_SUCCESS; blade_handle_transport_registration_t *bhtr = NULL; const char *tname = NULL; - + ks_assert(bh); ks_assert(target); @@ -482,6 +482,55 @@ KS_DECLARE(ks_status_t) blade_handle_sessions_remove(blade_session_t *bs) } +KS_DECLARE(blade_request_t *) blade_handle_requests_get(blade_handle_t *bh, const char *mid) +{ + blade_request_t *br = NULL; + + ks_assert(bh); + ks_assert(mid); + + ks_hash_read_lock(bh->requests); + br = ks_hash_search(bh->requests, (void *)mid, KS_UNLOCKED); + ks_hash_read_unlock(bh->requests); + + return br; +} + +KS_DECLARE(ks_status_t) blade_handle_requests_add(blade_request_t *br) +{ + ks_status_t ret = KS_STATUS_SUCCESS; + blade_handle_t *bh = NULL; + + ks_assert(br); + + bh = br->handle; + ks_assert(bh); + + ks_hash_write_lock(bh->requests); + ret = ks_hash_insert(bh->requests, (void *)br->message_id, br); + ks_hash_write_unlock(bh->requests); + + return ret; +} + +KS_DECLARE(ks_status_t) blade_handle_requests_remove(blade_request_t *br) +{ + ks_status_t ret = KS_STATUS_SUCCESS; + blade_handle_t *bh = NULL; + + ks_assert(br); + + bh = br->handle; + ks_assert(bh); + + ks_hash_write_lock(bh->requests); + if (ks_hash_remove(bh->requests, (void *)br->message_id) == NULL) ret = KS_STATUS_FAIL; + ks_hash_write_unlock(bh->requests); + + return ret; +} + + KS_DECLARE(ks_bool_t) blade_handle_datastore_available(blade_handle_t *bh) { @@ -499,7 +548,7 @@ KS_DECLARE(ks_status_t) blade_handle_datastore_store(blade_handle_t *bh, const v ks_assert(data_length > 0); if (!blade_handle_datastore_available(bh)) return KS_STATUS_INACTIVE; - + return blade_datastore_store(bh->datastore, key, key_length, data, data_length); } @@ -513,9 +562,9 @@ KS_DECLARE(ks_status_t) blade_handle_datastore_fetch(blade_handle_t *bh, ks_assert(callback); ks_assert(key); ks_assert(key_length > 0); - + if (!blade_handle_datastore_available(bh)) return KS_STATUS_INACTIVE; - + return blade_datastore_fetch(bh->datastore, callback, key, key_length, userdata); } diff --git a/libs/libblade/src/include/blade_protocol.h b/libs/libblade/src/include/blade_protocol.h index fcd89cc01a..ddc4a3cdee 100644 --- a/libs/libblade/src/include/blade_protocol.h +++ b/libs/libblade/src/include/blade_protocol.h @@ -1,23 +1,23 @@ /* * Copyright (c) 2017, Shane Bryldt * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -36,8 +36,10 @@ #include KS_BEGIN_EXTERN_C -KS_DECLARE(ks_status_t) blade_request_create(blade_request_t **breqP, ks_pool_t *pool, const char *session_id, cJSON *json /*, response_callback*/); +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_destroy(blade_request_t **breqP); +KS_DECLARE(ks_status_t) blade_response_create(blade_response_t **bresP, blade_handle_t *bh, const char *session_id, blade_request_t *breq, cJSON *json); +KS_DECLARE(ks_status_t) blade_response_destroy(blade_response_t **bresP); KS_END_EXTERN_C #endif diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h index dd1affb71d..ff86af388e 100644 --- a/libs/libblade/src/include/blade_stack.h +++ b/libs/libblade/src/include/blade_stack.h @@ -1,23 +1,23 @@ /* * Copyright (c) 2007-2014, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -55,11 +55,15 @@ KS_DECLARE(ks_status_t) blade_handle_connect(blade_handle_t *bh, blade_connectio KS_DECLARE(blade_connection_t *) blade_handle_connections_get(blade_handle_t *bh, const char *cid); KS_DECLARE(ks_status_t) blade_handle_connections_add(blade_connection_t *bc); 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(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(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_remove(blade_request_t *br); + KS_DECLARE(ks_bool_t) blade_handle_datastore_available(blade_handle_t *bh); KS_DECLARE(ks_status_t) blade_handle_datastore_store(blade_handle_t *bh, const void *key, int32_t key_length, const void *data, int64_t data_length); KS_DECLARE(ks_status_t) blade_handle_datastore_fetch(blade_handle_t *bh, diff --git a/libs/libblade/src/include/blade_types.h b/libs/libblade/src/include/blade_types.h index 66e8ea0d01..295217979d 100644 --- a/libs/libblade/src/include/blade_types.h +++ b/libs/libblade/src/include/blade_types.h @@ -1,23 +1,23 @@ /* * Copyright (c) 2007-2014, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -141,8 +141,8 @@ struct blade_transport_callbacks_s { struct blade_request_s { + blade_handle_t *handle; ks_pool_t *pool; - uint32_t refs; const char *session_id; cJSON *message; @@ -152,8 +152,8 @@ struct blade_request_s { }; struct blade_response_s { + blade_handle_t *handle; ks_pool_t *pool; - uint32_t refs; const char *session_id; blade_request_t *request;