- diff --git a/libs/libblade/src/blade_connection.c b/libs/libblade/src/blade_connection.c
- new file mode 100644
- index 0000000..cebc027
- --- /dev/null
- +++ b/libs/libblade/src/blade_connection.c
- @@ -0,0 +1,209 @@
- +/*
- + * 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_connection_s {
- + blade_handle_t *handle;
- + ks_pool_t *pool;
- +
- + void *transport_data;
- + blade_transport_callbacks_t *transport_callbacks;
- +
- + ks_bool_t shutdown;
- + ks_thread_t *state_thread;
- + blade_connection_state_t state;
- +
- + ks_q_t *sending;
- + ks_q_t *receiving;
- +};
- +
- +void *blade_connection_state_thread(ks_thread_t *thread, void *data);
- +
- +
- +KS_DECLARE(ks_status_t) blade_connection_create(blade_connection_t **bcP,
- + blade_handle_t *bh,
- + void *transport_data,
- + blade_transport_callbacks_t *transport_callbacks)
- +{
- + blade_connection_t *bc = NULL;
- + ks_pool_t *pool = NULL;
- +
- + ks_assert(bcP);
- + ks_assert(bh);
- + ks_assert(transport_data);
- + ks_assert(transport_callbacks);
- +
- + pool = blade_handle_pool_get(bh);
- +
- + bc = ks_pool_alloc(pool, sizeof(blade_connection_t));
- + bc->handle = bh;
- + bc->pool = pool;
- + bc->transport_data = transport_data;
- + bc->transport_callbacks = transport_callbacks;
- + bc->state = BLADE_CONNECTION_STATE_NONE;
- + ks_q_create(&bp->sending, pool, 0);
- + ks_q_create(&bp->receiving, pool, 0);
- + *bcP = bc;
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_connection_destroy(blade_connection_t **bcP)
- +{
- + blade_connection_t *bc = NULL;
- +
- + ks_assert(bcP);
- + ks_assert(*bcP);
- +
- + bc = *bcP;
- +
- + blade_connection_shutdown(bc);
- +
- + ks_q_destroy(&bc->sending);
- + ks_q_destroy(&bc->receiving);
- +
- + ks_pool_free(bc->pool, bcP);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_connection_startup(blade_connection_t *bc)
- +{
- + ks_assert(bc);
- +
- + bc->state = BLADE_CONNECTION_STATE_NONE;
- +
- + if (ks_thread_create_ex(&bc->state_thread,
- + blade_connection_state_thread,
- + bc,
- + KS_THREAD_FLAG_DEFAULT,
- + KS_THREAD_DEFAULT_STACK,
- + KS_PRI_NORMAL,
- + bc->pool) != KS_STATUS_SUCCESS) {
- + // @todo error logging
- + blade_connection_disconnect(bc);
- + return KS_STATUS_FAIL;
- + }
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_connection_shutdown(blade_connection_t *bc)
- +{
- + ks_assert(bc);
- +
- + if (bc->state_thread) {
- + bc->shutdown = KS_TRUE;
- + ks_thread_join(bp->kws_thread);
- + ks_pool_free(bp->pool, &bp->kws_thread);
- + bc->shutdown = KS_FALSE;
- + }
- +
- + //while (ks_q_trypop(bc->sending, (void **)&message) == KS_STATUS_SUCCESS && message) blade_message_discard(&message);
- + //while (ks_q_trypop(bc->receiving, (void **)&message) == KS_STATUS_SUCCESS && message) blade_message_discard(&message);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(void) blade_connection_disconnect(blade_connection_t *bc)
- +{
- + ks_assert(bc);
- +
- + bc->state = BLADE_CONNECTION_STATE_DISCONNECT;
- +}
- +
- +KS_DECLARE(void *) blade_connection_transport_get(blade_connection_t *bc)
- +{
- + ks_assert(bc);
- +
- + return bc->transport_data;
- +}
- +
- +KS_DECLARE(blade_connection_state_t) blade_connection_state_get(blade_connection_t *bc)
- +{
- + ks_assert(bc);
- +
- + return bc->state;
- +}
- +
- +KS_DECLARE(void) blade_connection_state_set(blade_connection_t *bc, blade_connection_state_t state)
- +{
- + ks_assert(bc);
- +
- + bc->state = state;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_connection_sending_push(blade_connection_t *bc, blade_identity_t *target, cJSON *json)
- +{
- + ks_assert(bc);
- + ks_assert(json);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_connection_sending_pop(blade_connection_t *bc, blade_identity_t **target, cJSON **json)
- +{
- + ks_assert(bc);
- + ks_assert(json);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +void *blade_connection_state_thread(ks_thread_t *thread, void *data)
- +{
- + blade_connection_t *bc = NULL;
- +
- + ks_assert(thread);
- + ks_assert(data);
- +
- + bc = (blade_connection_t *)data;
- +
- + while (!bc->shutdown) {
- + if (bc->transport_callbacks->onpulse(bc) != KS_STATUS_SUCCESS)
- + blade_connection_disconnect(bc);
- + }
- +
- + return NULL;
- +}
- +
- +/* 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:
- + */
- diff --git a/libs/libblade/src/blade_module.c b/libs/libblade/src/blade_module.c
- new file mode 100644
- index 0000000..414e895
- --- /dev/null
- +++ b/libs/libblade/src/blade_module.c
- @@ -0,0 +1,96 @@
- +/*
- + * 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_module_s {
- + blade_handle_t *handle;
- + ks_pool_t *pool;
- +
- + 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)
- +{
- + blade_module_t *bm = NULL;
- + ks_pool_t *pool = NULL;
- +
- + ks_assert(bmP);
- + ks_assert(handle);
- + ks_assert(module_data);
- + ks_assert(module_callbacks);
- +
- + pool = blade_handle_pool_get(bh);
- +
- + bm = ks_pool_alloc(pool, sizeof(blade_module_t));
- + bm->handle = bh;
- + bm->pool = pool;
- + bm->module_data = module_data;
- + bm->module_callbacks = module_callbacks;
- + *bmP = bm;
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_module_destroy(blade_module_t **bmP)
- +{
- + ks_assert(bmP);
- +
- + ks_pool_free(bm->pool, bmP);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +KS_DECLARE(ks_status_t) blade_module_data_get(blade_module_t *bm, void **data)
- +{
- + ks_assert(bm);
- + ks_assert(data);
- +
- + *data = bm->module_data;
- +
- + 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:
- + */
- diff --git a/libs/libblade/src/blade_module_wss.c b/libs/libblade/src/blade_module_wss.c
- new file mode 100644
- index 0000000..589a172
- --- /dev/null
- +++ b/libs/libblade/src/blade_module_wss.c
- @@ -0,0 +1,626 @@
- +/*
- + * 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"
- +
- +#define BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX 16
- +
- +typedef struct blade_transport_wss_s blade_transport_wss_t;
- +
- +struct blade_module_wss_s {
- + blade_handle_t *handle;
- + ks_pool_t *pool;
- + ks_thread_pool_t *tpool;
- + blade_module_callbacks_t *module_callbacks;
- + blade_transport_callbacks_t *transport_callbacks;
- +
- + ks_sockaddr_t config_wss_endpoints_ipv4[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
- + ks_sockaddr_t config_wss_endpoints_ipv6[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
- + int32_t config_wss_endpoints_ipv4_length;
- + int32_t config_wss_endpoints_ipv6_length;
- + int32_t config_wss_endpoints_backlog;
- +
- + ks_bool_t shutdown;
- +
- + ks_thread_t *listeners_thread;
- + struct pollfd *listeners_poll;
- + int32_t listeners_count;
- +
- + list_t connected;
- + ks_q_t *disconnecting;
- +};
- +
- +struct blade_transport_wss_s {
- + blade_module_wss_t *module;
- + ks_pool_t *pool;
- +
- + ks_socket_t sock;
- + kws_t *kws;
- +};
- +
- +
- +
- +//ks_status_t blade_module_wss_create(blade_module_wss_t **bm_wssP, blade_handle_t *bh);
- +//ks_status_t blade_module_wss_destroy(blade_module_wss_t **bm_wssP);
- +
- +ks_status_t blade_module_wss_onload(blade_module_t **bmP, blade_handle_t *bh);
- +ks_status_t blade_module_wss_onunload(blade_module_t *bm);
- +ks_status_t blade_module_wss_onstartup(blade_module_t *bm, config_setting_t *config);
- +ks_status_t blade_module_wss_onshutdown(blade_module_t *bm);
- +
- +ks_status_t blade_module_wss_listen(blade_module_wss_t *bm, ks_sockaddr_t *addr);
- +void *blade_module_wss_listeners_thread(ks_thread_t *thread, void *data);
- +
- +
- +ks_status_t blade_transport_wss_create(blade_transport_wss_t **bt_wssP, blade_module_wss_t *bm_wss, ks_socket_t sock);
- +ks_status_t blade_transport_wss_destroy(blade_transport_wss_t **bt_wssP);
- +
- +ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target);
- +ks_status_t blade_transport_wss_onpulse(blade_connection_t *bc);
- +
- +
- +
- +static blade_module_wss_t g_module_wss; // @todo temporary, should be instanced in case multiple handles are created
- +
- +static blade_module_callbacks_t g_module_wss_callbacks =
- +{
- + blade_module_wss_onload,
- + blade_module_wss_onunload,
- + blade_module_wss_onstartup,
- + blade_module_wss_onshutdown,
- +};
- +
- +static blade_transport_callbacks_t g_transport_wss_callbacks =
- +{
- + blade_transport_wss_onconnect,
- + blade_transport_wss_onpulse,
- + // @todo callback for a transport to rank routability of an identity, like blade_transport_wss_onroute(identity)
- +};
- +
- +
- +
- +//ks_status_t blade_module_wss_create(blade_module_wss_t **bm_wssP, blade_handle_t *bh)
- +
- +//ks_status_t blade_module_wss_destroy(blade_module_wss_t **bm_wssP)
- +
- +ks_status_t blade_module_wss_onload(blade_module_t **bmP, blade_handle_t *bh)
- +{
- + ks_assert(bmP);
- + ks_assert(bh);
- +
- + memset(&g_module_wss, 0, sizeof(blade_module_wss_t));
- +
- + g_module_wss.handle = bh;
- + g_module_wss.pool = blade_handle_pool_get(bh);
- + g_module_wss.tpool = blade_handle_tpool_get(bh);
- + g_module_wss.module_callbacks = &g_module_wss_callbacks;
- + g_module_wss.transport_callbacks = &g_transport_wss_callbacks;
- + list_init(&g_module_wss.connected);
- + ks_q_create(&g_module_wss.disconnecting, g_module_wss.pool, 0);
- + ks_assert(g_module_wss.disconnecting);
- +
- + blade_module_create(bmP, bh, &g_module_wss, &g_module_wss_callbacks);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_module_wss_onunload(blade_module_t *bm)
- +{
- + ks_assert(bm);
- +
- + blade_module_destroy(&bm);
- +
- + blade_module_wss_shutdown(bm);
- +
- + //blade_module_wss_destroy(&bm);
- +
- + list_destroy(&g_module.connected);
- + ks_q_destroy(&g_module_wss.disconnecting);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_module_wss_config(blade_module_wss_t *bm_wss, config_setting_t *config)
- +{
- + config_setting_t *wss = NULL;
- + config_setting_t *wss_endpoints = NULL;
- + config_setting_t *wss_endpoints_ipv4 = NULL;
- + config_setting_t *wss_endpoints_ipv6 = NULL;
- + config_setting_t *wss_ssl = NULL;
- + config_setting_t *element;
- + config_setting_t *tmp1;
- + config_setting_t *tmp2;
- + ks_sockaddr_t config_wss_endpoints_ipv4[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
- + ks_sockaddr_t config_wss_endpoints_ipv6[BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX];
- + int32_t config_wss_endpoints_ipv4_length = 0;
- + int32_t config_wss_endpoints_ipv6_length = 0;
- + int32_t config_wss_endpoints_backlog = 8;
- +
- + ks_assert(bm_wss);
- + ks_assert(config);
- +
- + if (!config_setting_is_group(config)) {
- + ks_log(KS_LOG_DEBUG, "!config_setting_is_group(config)\n");
- + return KS_STATUS_FAIL;
- + }
- +
- + wss = config_setting_get_member(config, "wss");
- + if (!wss) {
- + ks_log(KS_LOG_DEBUG, "!wss\n");
- + return KS_STATUS_FAIL;
- + }
- + wss_endpoints = config_setting_get_member(wss, "endpoints");
- + if (!wss_endpoints) {
- + ks_log(KS_LOG_DEBUG, "!wss_endpoints\n");
- + return KS_STATUS_FAIL;
- + }
- + wss_endpoints_ipv4 = config_lookup_from(wss_endpoints, "ipv4");
- + wss_endpoints_ipv6 = config_lookup_from(wss_endpoints, "ipv6");
- + if (wss_endpoints_ipv4) {
- + if (config_setting_type(wss_endpoints_ipv4) != CONFIG_TYPE_LIST) return KS_STATUS_FAIL;
- + if ((config_wss_endpoints_ipv4_length = config_setting_length(wss_endpoints_ipv4)) > BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX)
- + return KS_STATUS_FAIL;
- +
- + for (int32_t index = 0; index < config_wss_endpoints_ipv4_length; ++index) {
- + element = config_setting_get_elem(wss_endpoints_ipv4, index);
- + tmp1 = config_lookup_from(element, "address");
- + tmp2 = config_lookup_from(element, "port");
- + if (!tmp1 || !tmp2) return KS_STATUS_FAIL;
- + if (config_setting_type(tmp1) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL;
- + if (config_setting_type(tmp2) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
- +
- + if (ks_addr_set(&config_wss_endpoints_ipv4[index],
- + config_setting_get_string(tmp1),
- + config_setting_get_int(tmp2),
- + AF_INET) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
- + ks_log(KS_LOG_DEBUG,
- + "Binding to IPV4 %s on port %d\n",
- + ks_addr_get_host(&config_wss_endpoints_ipv4[index]),
- + ks_addr_get_port(&config_wss_endpoints_ipv4[index]));
- + }
- + }
- + if (wss_endpoints_ipv6) {
- + if (config_setting_type(wss_endpoints_ipv6) != CONFIG_TYPE_LIST) return KS_STATUS_FAIL;
- + if ((config_wss_endpoints_ipv6_length = config_setting_length(wss_endpoints_ipv6)) > BLADE_MODULE_WSS_ENDPOINTS_MULTIHOME_MAX)
- + return KS_STATUS_FAIL;
- +
- + for (int32_t index = 0; index < config_wss_endpoints_ipv6_length; ++index) {
- + element = config_setting_get_elem(wss_endpoints_ipv6, index);
- + tmp1 = config_lookup_from(element, "address");
- + tmp2 = config_lookup_from(element, "port");
- + if (!tmp1 || !tmp2) return KS_STATUS_FAIL;
- + if (config_setting_type(tmp1) != CONFIG_TYPE_STRING) return KS_STATUS_FAIL;
- + if (config_setting_type(tmp2) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
- +
- +
- + if (ks_addr_set(&config_wss_endpoints_ipv6[index],
- + config_setting_get_string(tmp1),
- + config_setting_get_int(tmp2),
- + AF_INET6) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
- + ks_log(KS_LOG_DEBUG,
- + "Binding to IPV6 %s on port %d\n",
- + ks_addr_get_host(&config_wss_endpoints_ipv6[index]),
- + ks_addr_get_port(&config_wss_endpoints_ipv6[index]));
- + }
- + }
- + if (config_wss_endpoints_ipv4_length + config_wss_endpoints_ipv6_length <= 0) return KS_STATUS_FAIL;
- + tmp1 = config_lookup_from(wss_endpoints, "backlog");
- + if (tmp1) {
- + if (config_setting_type(tmp1) != CONFIG_TYPE_INT) return KS_STATUS_FAIL;
- + config_wss_endpoints_backlog = config_setting_get_int(tmp1);
- + }
- + wss_ssl = config_setting_get_member(wss, "ssl");
- + if (wss_ssl) {
- + // @todo: SSL stuffs from wss_ssl into config_wss_ssl envelope
- + }
- +
- +
- + // Configuration is valid, now assign it to the variables that are used
- + // If the configuration was invalid, then this does not get changed
- + for (int32_t index = 0; index < config_wss_endpoints_ipv4_length; ++index)
- + bm_wss->config_wss_endpoints_ipv4[index] = config_wss_endpoints_ipv4[index];
- + for (int32_t index = 0; index < config_wss_endpoints_ipv6_length; ++index)
- + bm_wss->config_wss_endpoints_ipv6[index] = config_wss_endpoints_ipv6[index];
- + bm_wss->config_wss_endpoints_ipv4_length = config_wss_endpoints_ipv4_length;
- + bm_wss->config_wss_endpoints_ipv6_length = config_wss_endpoints_ipv6_length;
- + bm_wss->config_wss_endpoints_backlog = config_wss_endpoints_backlog;
- + //bm_wss->config_wss_ssl = config_wss_ssl;
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_module_wss_onstartup(blade_module_t *bm, config_setting_t *config)
- +{
- + blade_module_wss_t *bm_wss = NULL;
- +
- + ks_assert(bm);
- + ks_assert(config);
- +
- + bm_wss = (blade_module_wss_t *)blade_module_data_get(bm);
- +
- + if (blade_module_wss_config(bm_wss, config) != KS_STATUS_SUCCESS) {
- + ks_log(KS_LOG_DEBUG, "blade_module_wss_config failed\n");
- + return KS_STATUS_FAIL;
- + }
- +
- + for (int32_t index = 0; index < bm_wss->config_wss_endpoints_ipv4_length; ++index) {
- + if (blade_module_wss_listen(bm_wss, &bm_wss->config_wss_endpoints_ipv4[index]) != KS_STATUS_SUCCESS) {
- + ks_log(KS_LOG_DEBUG, "blade_module_wss_listen (v4) failed\n");
- + return KS_STATUS_FAIL;
- + }
- + }
- + for (int32_t index = 0; index < bm_wss->config_wss_endpoints_ipv6_length; ++index) {
- + if (blade_module_wss_listen(bm_wss, &bm_wss->config_wss_endpoints_ipv6[index]) != KS_STATUS_SUCCESS) {
- + ks_log(KS_LOG_DEBUG, "blade_module_wss_listen (v6) failed\n");
- + return KS_STATUS_FAIL;
- + }
- + }
- +
- + if (ks_thread_create_ex(&bm_wss->listeners_thread,
- + blade_module_wss_listeners_thread,
- + bm_wss,
- + KS_THREAD_FLAG_DEFAULT,
- + KS_THREAD_DEFAULT_STACK,
- + KS_PRI_NORMAL,
- + bm_wss->pool) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_module_wss_onshutdown(blade_module_t *bm)
- +{
- + blade_module_wss_t *bm_wss = NULL;
- + blade_transport_wss_t *bt_wss = NULL;
- + blade_connection_t *conn = NULL;
- +
- + ks_assert(bm);
- +
- + bm_wss = (blade_module_wss_t *)blade_module_data_get(bm);
- +
- + if (bm_wss->listeners_thread) {
- + bm_wss->shutdown = KS_TRUE;
- + ks_thread_join(bm_wss->listeners_thread);
- + ks_pool_free(bm_wss->pool, &bm_wss->listeners_thread);
- + bm_wss->shutdown = KS_FALSE;
- + }
- +
- + for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
- + ks_socket_t sock = bm_wss->listeners_poll[index].fd;
- + ks_socket_shutdown(sock, SHUT_RDWR);
- + ks_socket_close(&sock);
- + }
- + bm_wss->listeners_count = 0;
- + if (bm_wss->listeners_poll) ks_pool_free(bm_wss->pool, &bm_wss->listeners_poll);
- +
- + while (ks_q_trypop(bm_wss->disconnecting, &conn) == KS_STATUS_SUCCESS) ;
- + list_iterator_start(&bm_wss->connected);
- + while (list_iterator_hasnext(&bm_wss->connected)) {
- + conn = (blade_connection_t *)list_iterator_next(&bm_wss->connected);
- + trans = (blade_transport_wss_t *)blade_connection_transport_get(conn);
- +
- + blade_connection_destroy(&conn);
- + blade_transport_wss_destroy(&trans);
- + }
- + list_iterator_stop(&bm_wss->connected);
- + list_clear(&bm_wss->connected);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_module_wss_listen(blade_module_wss_t *bm_wss, ks_sockaddr_t *addr)
- +{
- + ks_socket_t listener = KS_SOCK_INVALID;
- + int32_t listener_index = -1;
- + ks_status_t ret = KS_STATUS_SUCCESS;
- +
- + ks_assert(bm_wss);
- + ks_assert(addr);
- +
- + if ((listener = socket(addr->family, SOCK_STREAM, IPPROTO_TCP)) == KS_SOCK_INVALID) {
- + ks_log(KS_LOG_DEBUG, "listener == KS_SOCK_INVALID\n");
- + ret = KS_STATUS_FAIL;
- + goto done;
- + }
- +
- + ks_socket_option(listener, SO_REUSEADDR, KS_TRUE);
- + ks_socket_option(listener, TCP_NODELAY, KS_TRUE);
- + if (addr->family == AF_INET6) ks_socket_option(listener, IPV6_V6ONLY, KS_TRUE);
- +
- + if (ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS) {
- + ks_log(KS_LOG_DEBUG, "ks_addr_bind(listener, addr) != KS_STATUS_SUCCESS\n");
- + ret = KS_STATUS_FAIL;
- + goto done;
- + }
- +
- + if (listen(listener, bm_wss->config_wss_endpoints_backlog) != 0) {
- + ks_log(KS_LOG_DEBUG, "listen(listener, backlog) != 0\n");
- + ret = KS_STATUS_FAIL;
- + goto done;
- + }
- +
- + listener_index = bm_wss->listeners_count++;
- + bm_wss->listeners_poll = (struct pollfd *)ks_pool_resize(bm_wss->pool,
- + bm_wss->listeners_poll,
- + sizeof(struct pollfd) * bm_wss->listeners_count);
- + ks_assert(bm_wss->listeners_poll);
- + bm_wss->listeners_poll[listener_index].fd = listener;
- + bm_wss->listeners_poll[listener_index].events = POLLIN | POLLERR;
- +
- + done:
- + if (ret != KS_STATUS_SUCCESS) {
- + if (listener != KS_SOCK_INVALID) {
- + ks_socket_shutdown(listener, SHUT_RDWR);
- + ks_socket_close(&listener);
- + }
- + }
- + return ret;
- +}
- +
- +void *blade_module_wss_listeners_thread(ks_thread_t *thread, void *data)
- +{
- + blade_module_wss_t *bm_wss = NULL;
- + blade_transport_wss_t *bt_wss = NULL;
- + blade_connection_t *bc = NULL;
- +
- + ks_assert(thread);
- + ks_assert(data);
- +
- + bm_wss = (blade_module_wss_t *)data;
- +
- + ks_log(KS_LOG_DEBUG, "Module running\n");
- +
- + while (!bm_wss->shutdown) {
- + // @todo take exact timeout from a setting in config_wss_endpoints
- + if (ks_poll(bm_wss->listeners_poll, bm_wss->listeners_count, 100) > 0) {
- + for (int32_t index = 0; index < bm_wss->listeners_count; ++index) {
- + ks_socket_t sock = KS_SOCK_INVALID;
- +
- + if (!(bm_wss->listeners_poll[index].revents & POLLIN)) continue;
- + if (bm_wss->listeners_poll[index].revents & POLLERR) {
- + // @todo: error handling, just skip the listener for now, it might recover, could skip X times before closing?
- + continue;
- + }
- +
- + if ((sock = accept(bm_wss->listeners_poll[index].fd, NULL, NULL)) == KS_SOCK_INVALID) {
- + // @todo: error handling, just skip the socket for now as most causes are because remote side became unreachable
- + continue;
- + }
- +
- + blade_transport_wss_create(&bt_wss, bm_wss, sock);
- + ks_assert(bt_wss);
- +
- + blade_connection_create(&bc, bm_wss->handle, bt_wss, bm_wss->transport_callbacks);
- + ks_assert(bc);
- +
- + blade_connection_startup(bc);
- +
- + list_append(&bm_wss->connected, bc);
- +
- + blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NEW);
- + }
- + }
- +
- + while (ks_q_trypop(bm_wss->disconnecting, &bc) == KS_STATUS_SUCCESS) {
- + bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
- +
- + list_delete(&bm_wss->connected, bc);
- +
- + blade_connection_destroy(&bc);
- + blade_transport_wss_destroy(&bt_wss);
- + }
- + }
- +
- + return NULL;
- +}
- +
- +
- +
- +ks_status_t blade_transport_wss_create(blade_transport_wss_t **bt_wssP, blade_module_wss_t *bm_wss, ks_socket_t sock)
- +{
- + blade_transport_wss_t *bt_wss = NULL;
- +
- + ks_assert(bt_wssP);
- + ks_assert(bm_wss);
- + ks_assert(sock != KS_SOCK_INVALID);
- +
- + bt_wss = ks_pool_alloc(bm_wss->pool, sizeof(blade_transport_wss_t));
- + bt_wss->module = bm_wss;
- + bt_wss->pool = bm_wss->pool;
- + bt_wss->sock = sock;
- +
- + *bt_wssP = bt_wss;
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_destroy(blade_transport_wss_t **bt_wssP)
- +{
- + blade_transport_wss_t *bt_wss = NULL;
- +
- + ks_assert(bt_wssP);
- + ks_assert(*bt_wssP);
- +
- + bt_wss = *bt_wssP;
- +
- + if (bt_wss->kws) kws_destroy(&bt_wss->kws);
- + else ks_socket_close(bt_wss->sock);
- +
- + ks_pool_free(bt_wss->pool, bt_wssP);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_onconnect(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target)
- +{
- + ks_assert(bcP);
- + ks_assert(bh);
- + ks_assert(target);
- +
- + *bcP = NULL;
- +
- + // @todo connect-out equivilent of accept
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_read(blade_transport_wss_t *bt_wss, cJSON **json)
- +{
- + // @todo get exact timeout from service config?
- + int32_t poll_flags = ks_wait_sock(bt_wss->sock, 100, KS_POLL_READ | KS_POLL_ERROR);
- +
- + *json = NULL;
- +
- + if (poll_flags & KS_POLL_ERROR) {
- + // @todo error logging
- + return KS_STATUS_FAIL;
- + }
- + if (poll_flags & KS_POLL_READ) {
- + kws_opcode_t opcode;
- + uint8_t *frame_data = NULL;
- + ks_size_t frame_data_len = kws_read_frame(bt_wss->kws, &opcode, &frame_data);
- +
- + if (frame_data_len <= 0) {
- + // @todo error logging, strerror(ks_errno())
- + // 0 means socket closed with WS_NONE, which closes websocket with no additional reason
- + // -1 means socket closed with a general failure
- + // -2 means nonblocking wait
- + // other values are based on WS_XXX reasons
- + // negative values are based on reasons, except for -1 is but -2 is nonblocking wait, and
- + return KS_STATUS_FAIL;
- + }
- +
- + //if (blade_handle_message_claim(blade_service_handle(peer->service), &message, frame_data, frame_data_len) != KS_STATUS_SUCCESS || !message) {
- + // @todo error logging
- + // return KS_STATUS_FAIL;
- + //}
- +
- + // @todo convert frame_data to cJSON safely, make sure data is null-terminated at frame_data_len
- + if (!(*json = cJSON_Parse(frame_data))) {
- + return KS_STATUS_FAIL;
- + }
- + }
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_write(blade_transport_wss_t *bt_wss, cJSON *json)
- +{
- + //blade_message_get(message, &target, &json);
- + char *json_str = cJSON_PrintUnformatted(json);
- + ks_size_t json_str_len = 0;
- + if (!json_str) {
- + // @todo error logging
- + return KS_STATUS_FAIL;
- + }
- + json_str_len = strlen(json_str) + 1;
- + kws_write_frame(bt_wss->kws, WSOC_TEXT, json_str, json_str_len);
- +
- + cJSON_free(jsonstr);
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_onpulse(blade_connection_t *bc)
- +{
- + blade_connection_state_t state;
- + blade_transport_wss_t *bt_wss = NULL;
- + cJSON *json = NULL;
- +
- + ks_assert(bc);
- +
- + state = blade_connection_state_get(bc);
- + bt_wss = (blade_transport_wss_t *)blade_connection_transport_get(bc);
- +
- + switch (state) {
- + case BLADE_CONNECTION_STATE_NEW:
- + {
- + // @todo: SSL init stuffs based on data from peer->service->config_websockets_ssl to pass into kws_init
- + if (kws_init(&bt_wss->kws, bt_wss->sock, NULL, NULL, KWS_BLOCK, bt_wss->pool) != KS_STATUS_SUCCESS) {
- + // @todo error logging
- + return KS_STATUS_FAIL;
- + }
- + blade_connection_state_set(bc, BLADE_CONNECTION_STATE_CONNECTIN);
- + break;
- + }
- + case BLADE_CONNECTION_STATE_DISCONNECT:
- + {
- + ks_q_push(bt_wss->module->disconnecting, conn);
- + blade_connection_state_set(bc, BLADE_CONNECTION_STATE_NONE);
- + break;
- + }
- + case BLADE_CONNECTION_STATE_CONNECTIN:
- + {
- + if (blade_transport_wss_read(bt_wss, &json) != KS_STATUS_SUCCESS) return KS_STATUS_FAIL;
- +
- + if (json) {
- + // @todo processing connectin messages for identity registration
- + cJSON_Delete(json);
- + //blade_connection_receiving_push(conn, json);
- + }
- +
- + // @todo wrap identity + json into an envelope for queueing through the connection, but target should be included in the json already
- + while (blade_connection_sending_pop(conn, (void **)&json) == KS_STATUS_SUCCESS && json) {
- + ks_status_t ret = blade_transport_wss_write(bt_wss, json);
- + cJSON_Delete(json);
- + if (ret != KS_STATUS_SUCCESS) return ret;
- + }
- + break;
- + }
- + default: break;
- + }
- +
- + return KS_STATUS_SUCCESS;
- +}
- +
- +ks_status_t blade_transport_wss_onsend(blade_connection_t *bc, blade_identity_t *target, cJSON *message)
- +{
- + //blade_transport_wss_t *trans = NULL;
- +
- + ks_assert(bc);
- + ks_assert(target);
- + ks_assert(message);
- +
- + //trans = (blade_transport_wss_t *)blade_connection_transport_get(bc);
- +
- + 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:
- + */
- diff --git a/libs/libblade/src/blade_stack.c b/libs/libblade/src/blade_stack.c
- index 8504af0..688136c 100644
- --- a/libs/libblade/src/blade_stack.c
- +++ b/libs/libblade/src/blade_stack.c
- @@ -184,6 +184,18 @@ KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh)
- return KS_STATUS_SUCCESS;
- }
- +KS_DECLARE(ks_pool_t *) blade_handle_pool_get(blade_handle_t *bh)
- +{
- + ks_assert(bh);
- + return bh->pool;
- +}
- +
- +KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh)
- +{
- + ks_assert(bh);
- + return bh->tpool;
- +}
- +
- KS_DECLARE(ks_status_t) blade_handle_message_claim(blade_handle_t *bh, blade_message_t **message, void *data, ks_size_t data_length)
- {
- blade_message_t *msg = NULL;
- diff --git a/libs/libblade/src/include/blade.h b/libs/libblade/src/include/blade.h
- index f8a3a44..e749212 100644
- --- a/libs/libblade/src/include/blade.h
- +++ b/libs/libblade/src/include/blade.h
- @@ -46,6 +46,8 @@
- #include "blade_datastore.h"
- #include "bpcp.h"
- +#include "blade_module.h"
- +
- KS_BEGIN_EXTERN_C
- KS_DECLARE(ks_status_t) blade_init(void);
- diff --git a/libs/libblade/src/include/blade_module.h b/libs/libblade/src/include/blade_module.h
- new file mode 100644
- index 0000000..d9fcca8
- --- /dev/null
- +++ b/libs/libblade/src/include/blade_module.h
- @@ -0,0 +1,55 @@
- +/*
- + * 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.
- + */
- +
- +#ifndef _BLADE_MODULE_H_
- +#define _BLADE_MODULE_H_
- +#include <blade.h>
- +
- +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_destroy(blade_module_t **bmP);
- +KS_DECLARE(ks_status_t) blade_module_data_get(blade_module_t *bm, void **data);
- +KS_END_EXTERN_C
- +
- +#endif
- +
- +/* 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:
- + */
- diff --git a/libs/libblade/src/include/blade_stack.h b/libs/libblade/src/include/blade_stack.h
- index ff44f23..57ac554 100644
- --- a/libs/libblade/src/include/blade_stack.h
- +++ b/libs/libblade/src/include/blade_stack.h
- @@ -45,6 +45,8 @@ KS_DECLARE(ks_status_t) blade_handle_destroy(blade_handle_t **bhP);
- 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_startup(blade_handle_t *bh, config_setting_t *config, blade_service_peer_state_callback_t service_peer_state_callback);
- KS_DECLARE(ks_status_t) blade_handle_shutdown(blade_handle_t *bh);
- +KS_DECLARE(ks_pool_t *) blade_handle_pool_get(blade_handle_t *bh);
- +KS_DECLARE(ks_thread_pool_t *) blade_handle_tpool_get(blade_handle_t *bh);
- KS_DECLARE(ks_status_t) blade_handle_message_claim(blade_handle_t *bh, blade_message_t **message, void *data, ks_size_t data_length);
- KS_DECLARE(ks_status_t) blade_handle_message_discard(blade_handle_t *bh, blade_message_t **message);
- diff --git a/libs/libblade/src/include/blade_types.h b/libs/libblade/src/include/blade_types.h
- index b534fde..966de73 100644
- --- a/libs/libblade/src/include/blade_types.h
- +++ b/libs/libblade/src/include/blade_types.h
- @@ -59,6 +59,33 @@ typedef struct blade_datastore_s blade_datastore_t;
- typedef void (*blade_service_peer_state_callback_t)(blade_service_t *bs, blade_peer_t *bp, blade_peerstate_t state);
- typedef ks_bool_t (*blade_datastore_fetch_callback_t)(blade_datastore_t *bds, const void *data, uint32_t data_length, void *userdata);
- +
- +
- +typedef struct blade_module_s blade_module_t;
- +typedef struct blade_module_callbacks_s blade_module_callbacks_t;
- +typedef struct blade_transport_callbacks_s blade_transport_callbacks_t;
- +
- +typedef ks_status_t (*blade_module_load_callback_t)(blade_module_t **bmP, blade_handle_t *bh);
- +typedef ks_status_t (*blade_module_unload_callback_t)(blade_module_t *bm);
- +typedef ks_status_t (*blade_module_startup_callback_t)(blade_module_t *bm, config_setting_t *config);
- +typedef ks_status_t (*blade_module_shutdown_callback_t)(blade_module_t *bm);
- +
- +struct blade_module_callbacks_s {
- + blade_module_load_callback_t onload;
- + blade_module_unload_callback_t onunload;
- + blade_module_startup_callback_t onstartup;
- + blade_module_shutdown_callback_t onshutdown;
- +};
- +
- +typedef ks_status_t (*blade_transport_connect_callback_t)(blade_connection_t **bcP, blade_module_t *bm, blade_identity_t *target);
- +typedef ks_status_t (*blade_transport_pulse_callback_t)(blade_connection_t *bc);
- +
- +struct blade_transport_callbacks_s {
- + blade_transport_connect_callback_t onconnect;
- + blade_transport_pulse_callback_t onpulse;
- +};
- +
- +
- KS_END_EXTERN_C
- #endif