From 9a22d1cb9213650524e7d3fb0677b1e43ace2d3a Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Thu, 23 Mar 2017 16:36:21 +0200 Subject: [PATCH] Compile filter.c as C++ The contents of the existing filter.cc was copied into filter.c that subsequently was renamed to filter.cc. The way the session is called as the last filter in the filter chain is really dubious and ought to be rearranged so that the blind casting of a session to a filter and back is not needed. --- include/maxscale/session.h | 15 +- server/core/CMakeLists.txt | 3 +- server/core/filter.c | 474 --------------------------------- server/core/filter.cc | 456 ++++++++++++++++++++++++++++++- server/core/maxscale/filter.h | 4 +- server/core/maxscale/session.h | 1 - server/core/session.c | 24 +- 7 files changed, 489 insertions(+), 488 deletions(-) delete mode 100644 server/core/filter.c diff --git a/include/maxscale/session.h b/include/maxscale/session.h index 92d38002a..41b396e27 100644 --- a/include/maxscale/session.h +++ b/include/maxscale/session.h @@ -94,11 +94,14 @@ typedef struct * The downstream element in the filter chain. This may refer to * another filter or to a router. */ +struct mxs_filter; +struct mxs_filter_session; + typedef struct mxs_downstream { - void *instance; - void *session; - int32_t (*routeQuery)(void *instance, void *session, GWBUF *request); + struct mxs_filter *instance; + struct mxs_filter_session *session; + int32_t (*routeQuery)(struct mxs_filter *instance, struct mxs_filter_session *session, GWBUF *request); } MXS_DOWNSTREAM; /** @@ -107,9 +110,9 @@ typedef struct mxs_downstream */ typedef struct mxs_upstream { - void *instance; - void *session; - int32_t (*clientReply)(void *instance, void *session, GWBUF *response); + struct mxs_filter *instance; + struct mxs_filter_session *session; + int32_t (*clientReply)(struct mxs_filter *instance, struct mxs_filter_session *session, GWBUF *response); int32_t (*error)(void *instance, void *session, void *); } MXS_UPSTREAM; diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index c8e0f256d..e5b09894d 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -7,7 +7,8 @@ add_library(maxscale-common SHARED config.cc config_runtime.cc dcb.cc - filter.c filter.cc externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c router.cc secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c) + filter.cc + externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c router.cc secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c) if(WITH_JEMALLOC) target_link_libraries(maxscale-common ${JEMALLOC_LIBRARIES}) diff --git a/server/core/filter.c b/server/core/filter.c deleted file mode 100644 index 948d7f1e2..000000000 --- a/server/core/filter.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (c) 2016 MariaDB Corporation Ab - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file and at www.mariadb.com/bsl11. - * - * Change Date: 2019-07-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2 or later of the General - * Public License. - */ - -/** - * @file filter.c - A representation of a filter within MaxScale. - * - * @verbatim - * Revision History - * - * Date Who Description - * 29/05/14 Mark Riddoch Initial implementation - * - * @endverbatim - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "maxscale/filter.h" - -#include "maxscale/config.h" -#include "maxscale/modules.h" - -static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */ -static MXS_FILTER_DEF *allFilters = NULL; /**< The list of all filters */ - -static void filter_free_parameters(MXS_FILTER_DEF *filter); - -/** - * Allocate a new filter within MaxScale - * - * - * @param name The filter name - * @param module The module to load - * - * @return The newly created filter or NULL if an error occured - */ -MXS_FILTER_DEF * -filter_alloc(const char *name, const char *module) -{ - char* my_name = MXS_STRDUP(name); - char* my_module = MXS_STRDUP(module); - - MXS_FILTER_DEF *filter = (MXS_FILTER_DEF *)MXS_MALLOC(sizeof(MXS_FILTER_DEF)); - - if (!my_name || !my_module || !filter) - { - MXS_FREE(my_name); - MXS_FREE(my_module); - MXS_FREE(filter); - return NULL; - } - filter->name = my_name; - filter->module = my_module; - filter->filter = NULL; - filter->options = NULL; - filter->obj = NULL; - filter->parameters = NULL; - - spinlock_init(&filter->spin); - - spinlock_acquire(&filter_spin); - filter->next = allFilters; - allFilters = filter; - spinlock_release(&filter_spin); - - return filter; -} - - -/** - * Deallocate the specified filter - * - * @param filter The filter to deallocate - * @return Returns true if the server was freed - */ -void -filter_free(MXS_FILTER_DEF *filter) -{ - MXS_FILTER_DEF *ptr; - - if (filter) - { - /* First of all remove from the linked list */ - spinlock_acquire(&filter_spin); - if (allFilters == filter) - { - allFilters = filter->next; - } - else - { - ptr = allFilters; - while (ptr && ptr->next != filter) - { - ptr = ptr->next; - } - if (ptr) - { - ptr->next = filter->next; - } - } - spinlock_release(&filter_spin); - - /* Clean up session and free the memory */ - MXS_FREE(filter->name); - MXS_FREE(filter->module); - - if (filter->options) - { - for (int i = 0; filter->options[i]; i++) - { - MXS_FREE(filter->options[i]); - } - MXS_FREE(filter->options); - } - - filter_free_parameters(filter); - - MXS_FREE(filter); - } -} - -MXS_FILTER_DEF * -filter_def_find(const char *name) -{ - MXS_FILTER_DEF *filter; - - spinlock_acquire(&filter_spin); - filter = allFilters; - while (filter) - { - if (strcmp(filter->name, name) == 0) - { - break; - } - filter = filter->next; - } - spinlock_release(&filter_spin); - return filter; -} - -const char* filter_def_get_name(const MXS_FILTER_DEF* filter_def) -{ - return filter_def->name; -} - -const char* filter_def_get_module_name(const MXS_FILTER_DEF* filter_def) -{ - return filter_def->module; -} - -MXS_FILTER* filter_def_get_instance(const MXS_FILTER_DEF* filter_def) -{ - return filter_def->filter; -} - -/** - * Check a parameter to see if it is a standard filter parameter - * - * @param name Parameter name to check - */ -int -filter_standard_parameter(const char *name) -{ - if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0) - { - return 1; - } - return 0; -} - -/** - * Print all filters to a DCB - * - * Designed to be called within a debugger session in order - * to display all active filters within MaxScale - */ -void -dprintAllFilters(DCB *dcb) -{ - MXS_FILTER_DEF *ptr; - int i; - - spinlock_acquire(&filter_spin); - ptr = allFilters; - while (ptr) - { - dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name); - dcb_printf(dcb, "\tModule: %s\n", ptr->module); - if (ptr->options) - { - dcb_printf(dcb, "\tOptions: "); - for (i = 0; ptr->options && ptr->options[i]; i++) - { - dcb_printf(dcb, "%s ", ptr->options[i]); - } - dcb_printf(dcb, "\n"); - } - if (ptr->obj && ptr->filter) - { - ptr->obj->diagnostics(ptr->filter, NULL, dcb); - } - else - { - dcb_printf(dcb, "\tModule not loaded.\n"); - } - ptr = ptr->next; - } - spinlock_release(&filter_spin); -} - -/** - * Print filter details to a DCB - * - * Designed to be called within a debug CLI in order - * to display all active filters in MaxScale - */ -void -dprintFilter(DCB *dcb, const MXS_FILTER_DEF *filter) -{ - int i; - - dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name); - dcb_printf(dcb, "\tModule: %s\n", filter->module); - if (filter->options) - { - dcb_printf(dcb, "\tOptions: "); - for (i = 0; filter->options && filter->options[i]; i++) - { - dcb_printf(dcb, "%s ", filter->options[i]); - } - dcb_printf(dcb, "\n"); - } - if (filter->obj && filter->filter) - { - filter->obj->diagnostics(filter->filter, NULL, dcb); - } -} - -/** - * List all filters in a tabular form to a DCB - * - */ -void -dListFilters(DCB *dcb) -{ - MXS_FILTER_DEF *ptr; - int i; - - spinlock_acquire(&filter_spin); - ptr = allFilters; - if (ptr) - { - dcb_printf(dcb, "Filters\n"); - dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); - dcb_printf(dcb, "%-19s | %-15s | Options\n", - "Filter", "Module"); - dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); - } - while (ptr) - { - dcb_printf(dcb, "%-19s | %-15s | ", - ptr->name, ptr->module); - for (i = 0; ptr->options && ptr->options[i]; i++) - { - dcb_printf(dcb, "%s ", ptr->options[i]); - } - dcb_printf(dcb, "\n"); - ptr = ptr->next; - } - if (allFilters) - { - dcb_printf(dcb, - "--------------------+-----------------+----------------------------------------\n\n"); - } - spinlock_release(&filter_spin); -} - -/** - * Add a router option to a service - * - * @param filter The filter to add the option to - * @param option The option string - */ -void -filter_add_option(MXS_FILTER_DEF *filter, const char *option) -{ - int i; - - spinlock_acquire(&filter->spin); - if (filter->options == NULL) - { - filter->options = (char **)MXS_CALLOC(2, sizeof(char *)); - MXS_ABORT_IF_NULL(filter->options); - filter->options[0] = MXS_STRDUP_A(option); - filter->options[1] = NULL; - } - else - { - for (i = 0; filter->options[i]; i++) - { - ; - } - - filter->options = (char **)MXS_REALLOC(filter->options, (i + 2) * sizeof(char *)); - MXS_ABORT_IF_NULL(filter->options); - filter->options[i] = MXS_STRDUP_A(option); - MXS_ABORT_IF_NULL(filter->options[i]); - filter->options[i + 1] = NULL; - } - spinlock_release(&filter->spin); -} - -/** - * Add a router parameter to a service - * - * @param filter The filter to add the parameter to - * @param name The parameter name - * @param value The parameter value - */ -void -filter_add_parameter(MXS_FILTER_DEF *filter, const char *name, const char *value) -{ - CONFIG_CONTEXT ctx = {.object = ""}; - - config_add_param(&ctx, name, value); - ctx.parameters->next = filter->parameters; - filter->parameters = ctx.parameters; -} - -/** - * Free filter parameters - * @param filter Filter whose parameters are to be freed - */ -static void filter_free_parameters(MXS_FILTER_DEF *filter) -{ - config_parameter_free(filter->parameters); -} - -/** - * Load a filter module for use and create an instance of it for a service. - * @param filter Filter definition - * @return True if module was successfully loaded, false if an error occurred - */ -bool filter_load(MXS_FILTER_DEF* filter) -{ - bool rval = false; - if (filter) - { - if (filter->filter) - { - // Already loaded and created. - rval = true; - } - else - { - if (filter->obj == NULL) - { - /* Filter not yet loaded */ - if ((filter->obj = load_module(filter->module, MODULE_FILTER)) == NULL) - { - MXS_ERROR("Failed to load filter module '%s'.", filter->module); - } - } - - if (filter->obj) - { - ss_dassert(!filter->filter); - - if ((filter->filter = (filter->obj->createInstance)(filter->name, - filter->options, - filter->parameters))) - { - rval = true; - } - else - { - MXS_ERROR("Failed to create filter '%s' instance.", filter->name); - } - } - } - } - return rval; -} - -/** - * Connect the downstream filter chain for a filter. - * - * This will create the filter instance, loading the filter module, and - * conenct the fitler into the downstream chain. - * - * @param filter The filter to add into the chain - * @param session The client session - * @param downstream The filter downstream of this filter - * @return The downstream component for the next filter or NULL - * if the filter could not be created - */ -MXS_DOWNSTREAM * -filter_apply(MXS_FILTER_DEF *filter, MXS_SESSION *session, MXS_DOWNSTREAM *downstream) -{ - MXS_DOWNSTREAM *me; - - if ((me = (MXS_DOWNSTREAM *)MXS_CALLOC(1, sizeof(MXS_DOWNSTREAM))) == NULL) - { - return NULL; - } - me->instance = filter->filter; - me->routeQuery = (void *)(filter->obj->routeQuery); - - if ((me->session = filter->obj->newSession(me->instance, session)) == NULL) - { - MXS_FREE(me); - return NULL; - } - filter->obj->setDownstream(me->instance, me->session, downstream); - - return me; -} - -/** - * Connect a filter in the up stream filter chain for a session - * - * Note, the filter will have been created when the downstream chian was - * previously setup. - * Note all filters require to be in the upstream chain, so this routine - * may skip a filter if it does not provide an upstream interface. - * - * @param filter The fitler to add to the chain - * @param fsession The filter session - * @param upstream The filter that should be upstream of this filter - * @return The upstream component for the next filter - */ -MXS_UPSTREAM * -filter_upstream(MXS_FILTER_DEF *filter, void *fsession, MXS_UPSTREAM *upstream) -{ - MXS_UPSTREAM *me = NULL; - - /* - * The the filter has no setUpstream entry point then is does - * not require to see results and can be left out of the chain. - */ - if (filter->obj->setUpstream == NULL) - { - return upstream; - } - - if (filter->obj->clientReply != NULL) - { - if ((me = (MXS_UPSTREAM *)MXS_CALLOC(1, sizeof(MXS_UPSTREAM))) == NULL) - { - return NULL; - } - me->instance = filter->filter; - me->session = fsession; - me->clientReply = (void *)(filter->obj->clientReply); - filter->obj->setUpstream(me->instance, me->session, upstream); - } - return me; -} diff --git a/server/core/filter.cc b/server/core/filter.cc index 13f517f08..d67af9e4c 100644 --- a/server/core/filter.cc +++ b/server/core/filter.cc @@ -11,7 +11,462 @@ * Public License. */ +/** + * @file filter.c - A representation of a filter within MaxScale. + */ +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include "maxscale/filter.h" + +#include "maxscale/config.h" +#include "maxscale/modules.h" + +static SPINLOCK filter_spin = SPINLOCK_INIT; /**< Protects the list of all filters */ +static MXS_FILTER_DEF *allFilters = NULL; /**< The list of all filters */ + +static void filter_free_parameters(MXS_FILTER_DEF *filter); + +/** + * Allocate a new filter within MaxScale + * + * + * @param name The filter name + * @param module The module to load + * + * @return The newly created filter or NULL if an error occured + */ +MXS_FILTER_DEF * +filter_alloc(const char *name, const char *module) +{ + char* my_name = MXS_STRDUP(name); + char* my_module = MXS_STRDUP(module); + + MXS_FILTER_DEF *filter = (MXS_FILTER_DEF *)MXS_MALLOC(sizeof(MXS_FILTER_DEF)); + + if (!my_name || !my_module || !filter) + { + MXS_FREE(my_name); + MXS_FREE(my_module); + MXS_FREE(filter); + return NULL; + } + filter->name = my_name; + filter->module = my_module; + filter->filter = NULL; + filter->options = NULL; + filter->obj = NULL; + filter->parameters = NULL; + + spinlock_init(&filter->spin); + + spinlock_acquire(&filter_spin); + filter->next = allFilters; + allFilters = filter; + spinlock_release(&filter_spin); + + return filter; +} + + +/** + * Deallocate the specified filter + * + * @param filter The filter to deallocate + * @return Returns true if the server was freed + */ +void +filter_free(MXS_FILTER_DEF *filter) +{ + MXS_FILTER_DEF *ptr; + + if (filter) + { + /* First of all remove from the linked list */ + spinlock_acquire(&filter_spin); + if (allFilters == filter) + { + allFilters = filter->next; + } + else + { + ptr = allFilters; + while (ptr && ptr->next != filter) + { + ptr = ptr->next; + } + if (ptr) + { + ptr->next = filter->next; + } + } + spinlock_release(&filter_spin); + + /* Clean up session and free the memory */ + MXS_FREE(filter->name); + MXS_FREE(filter->module); + + if (filter->options) + { + for (int i = 0; filter->options[i]; i++) + { + MXS_FREE(filter->options[i]); + } + MXS_FREE(filter->options); + } + + filter_free_parameters(filter); + + MXS_FREE(filter); + } +} + +MXS_FILTER_DEF * +filter_def_find(const char *name) +{ + MXS_FILTER_DEF *filter; + + spinlock_acquire(&filter_spin); + filter = allFilters; + while (filter) + { + if (strcmp(filter->name, name) == 0) + { + break; + } + filter = filter->next; + } + spinlock_release(&filter_spin); + return filter; +} + +const char* filter_def_get_name(const MXS_FILTER_DEF* filter_def) +{ + return filter_def->name; +} + +const char* filter_def_get_module_name(const MXS_FILTER_DEF* filter_def) +{ + return filter_def->module; +} + +MXS_FILTER* filter_def_get_instance(const MXS_FILTER_DEF* filter_def) +{ + return filter_def->filter; +} + +/** + * Check a parameter to see if it is a standard filter parameter + * + * @param name Parameter name to check + */ +int +filter_standard_parameter(const char *name) +{ + if (strcmp(name, "type") == 0 || strcmp(name, "module") == 0) + { + return 1; + } + return 0; +} + +/** + * Print all filters to a DCB + * + * Designed to be called within a debugger session in order + * to display all active filters within MaxScale + */ +void +dprintAllFilters(DCB *dcb) +{ + MXS_FILTER_DEF *ptr; + int i; + + spinlock_acquire(&filter_spin); + ptr = allFilters; + while (ptr) + { + dcb_printf(dcb, "Filter %p (%s)\n", ptr, ptr->name); + dcb_printf(dcb, "\tModule: %s\n", ptr->module); + if (ptr->options) + { + dcb_printf(dcb, "\tOptions: "); + for (i = 0; ptr->options && ptr->options[i]; i++) + { + dcb_printf(dcb, "%s ", ptr->options[i]); + } + dcb_printf(dcb, "\n"); + } + if (ptr->obj && ptr->filter) + { + ptr->obj->diagnostics(ptr->filter, NULL, dcb); + } + else + { + dcb_printf(dcb, "\tModule not loaded.\n"); + } + ptr = ptr->next; + } + spinlock_release(&filter_spin); +} + +/** + * Print filter details to a DCB + * + * Designed to be called within a debug CLI in order + * to display all active filters in MaxScale + */ +void +dprintFilter(DCB *dcb, const MXS_FILTER_DEF *filter) +{ + int i; + + dcb_printf(dcb, "Filter %p (%s)\n", filter, filter->name); + dcb_printf(dcb, "\tModule: %s\n", filter->module); + if (filter->options) + { + dcb_printf(dcb, "\tOptions: "); + for (i = 0; filter->options && filter->options[i]; i++) + { + dcb_printf(dcb, "%s ", filter->options[i]); + } + dcb_printf(dcb, "\n"); + } + if (filter->obj && filter->filter) + { + filter->obj->diagnostics(filter->filter, NULL, dcb); + } +} + +/** + * List all filters in a tabular form to a DCB + * + */ +void +dListFilters(DCB *dcb) +{ + MXS_FILTER_DEF *ptr; + int i; + + spinlock_acquire(&filter_spin); + ptr = allFilters; + if (ptr) + { + dcb_printf(dcb, "Filters\n"); + dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); + dcb_printf(dcb, "%-19s | %-15s | Options\n", + "Filter", "Module"); + dcb_printf(dcb, "--------------------+-----------------+----------------------------------------\n"); + } + while (ptr) + { + dcb_printf(dcb, "%-19s | %-15s | ", + ptr->name, ptr->module); + for (i = 0; ptr->options && ptr->options[i]; i++) + { + dcb_printf(dcb, "%s ", ptr->options[i]); + } + dcb_printf(dcb, "\n"); + ptr = ptr->next; + } + if (allFilters) + { + dcb_printf(dcb, + "--------------------+-----------------+----------------------------------------\n\n"); + } + spinlock_release(&filter_spin); +} + +/** + * Add a router option to a service + * + * @param filter The filter to add the option to + * @param option The option string + */ +void +filter_add_option(MXS_FILTER_DEF *filter, const char *option) +{ + int i; + + spinlock_acquire(&filter->spin); + if (filter->options == NULL) + { + filter->options = (char **)MXS_CALLOC(2, sizeof(char *)); + MXS_ABORT_IF_NULL(filter->options); + filter->options[0] = MXS_STRDUP_A(option); + filter->options[1] = NULL; + } + else + { + for (i = 0; filter->options[i]; i++) + { + ; + } + + filter->options = (char **)MXS_REALLOC(filter->options, (i + 2) * sizeof(char *)); + MXS_ABORT_IF_NULL(filter->options); + filter->options[i] = MXS_STRDUP_A(option); + MXS_ABORT_IF_NULL(filter->options[i]); + filter->options[i + 1] = NULL; + } + spinlock_release(&filter->spin); +} + +/** + * Add a router parameter to a service + * + * @param filter The filter to add the parameter to + * @param name The parameter name + * @param value The parameter value + */ +void +filter_add_parameter(MXS_FILTER_DEF *filter, const char *name, const char *value) +{ + CONFIG_CONTEXT ctx = {.object = (char*)""}; + + config_add_param(&ctx, name, value); + ctx.parameters->next = filter->parameters; + filter->parameters = ctx.parameters; +} + +/** + * Free filter parameters + * @param filter Filter whose parameters are to be freed + */ +static void filter_free_parameters(MXS_FILTER_DEF *filter) +{ + config_parameter_free(filter->parameters); +} + +/** + * Load a filter module for use and create an instance of it for a service. + * @param filter Filter definition + * @return True if module was successfully loaded, false if an error occurred + */ +bool filter_load(MXS_FILTER_DEF* filter) +{ + bool rval = false; + if (filter) + { + if (filter->filter) + { + // Already loaded and created. + rval = true; + } + else + { + if (filter->obj == NULL) + { + /* Filter not yet loaded */ + if ((filter->obj = (MXS_FILTER_OBJECT*)load_module(filter->module, MODULE_FILTER)) == NULL) + { + MXS_ERROR("Failed to load filter module '%s'.", filter->module); + } + } + + if (filter->obj) + { + ss_dassert(!filter->filter); + + if ((filter->filter = (filter->obj->createInstance)(filter->name, + filter->options, + filter->parameters))) + { + rval = true; + } + else + { + MXS_ERROR("Failed to create filter '%s' instance.", filter->name); + } + } + } + } + return rval; +} + +/** + * Connect the downstream filter chain for a filter. + * + * This will create the filter instance, loading the filter module, and + * conenct the fitler into the downstream chain. + * + * @param filter The filter to add into the chain + * @param session The client session + * @param downstream The filter downstream of this filter + * @return The downstream component for the next filter or NULL + * if the filter could not be created + */ +MXS_DOWNSTREAM * +filter_apply(MXS_FILTER_DEF *filter, MXS_SESSION *session, MXS_DOWNSTREAM *downstream) +{ + MXS_DOWNSTREAM *me; + + if ((me = (MXS_DOWNSTREAM *)MXS_CALLOC(1, sizeof(MXS_DOWNSTREAM))) == NULL) + { + return NULL; + } + me->instance = filter->filter; + me->routeQuery = filter->obj->routeQuery; + + if ((me->session = filter->obj->newSession(me->instance, session)) == NULL) + { + MXS_FREE(me); + return NULL; + } + filter->obj->setDownstream(me->instance, me->session, downstream); + + return me; +} + +/** + * Connect a filter in the up stream filter chain for a session + * + * Note, the filter will have been created when the downstream chian was + * previously setup. + * Note all filters require to be in the upstream chain, so this routine + * may skip a filter if it does not provide an upstream interface. + * + * @param filter The fitler to add to the chain + * @param fsession The filter session + * @param upstream The filter that should be upstream of this filter + * @return The upstream component for the next filter + */ +MXS_UPSTREAM * +filter_upstream(MXS_FILTER_DEF *filter, MXS_FILTER_SESSION *fsession, MXS_UPSTREAM *upstream) +{ + MXS_UPSTREAM *me = NULL; + + /* + * The the filter has no setUpstream entry point then is does + * not require to see results and can be left out of the chain. + */ + if (filter->obj->setUpstream == NULL) + { + return upstream; + } + + if (filter->obj->clientReply != NULL) + { + if ((me = (MXS_UPSTREAM *)MXS_CALLOC(1, sizeof(MXS_UPSTREAM))) == NULL) + { + return NULL; + } + me->instance = filter->filter; + me->session = fsession; + me->clientReply = filter->obj->clientReply; + filter->obj->setUpstream(me->instance, me->session, upstream); + } + return me; +} + + namespace maxscale { @@ -58,4 +513,3 @@ void FilterSession::diagnostics(DCB* pDcb) } } - diff --git a/server/core/maxscale/filter.h b/server/core/maxscale/filter.h index 4cb037d56..4ebc40602 100644 --- a/server/core/maxscale/filter.h +++ b/server/core/maxscale/filter.h @@ -44,6 +44,8 @@ MXS_DOWNSTREAM *filter_apply(MXS_FILTER_DEF *filter_def, MXS_SESSION *session, M void filter_free(MXS_FILTER_DEF *filter_def); bool filter_load(MXS_FILTER_DEF *filter_def); int filter_standard_parameter(const char *name); -MXS_UPSTREAM *filter_upstream(MXS_FILTER_DEF *filter_def, void *fsession, MXS_UPSTREAM *upstream); +MXS_UPSTREAM *filter_upstream(MXS_FILTER_DEF *filter_def, + MXS_FILTER_SESSION *fsession, + MXS_UPSTREAM *upstream); MXS_END_DECLS diff --git a/server/core/maxscale/session.h b/server/core/maxscale/session.h index dbf11c6ff..ad2682795 100644 --- a/server/core/maxscale/session.h +++ b/server/core/maxscale/session.h @@ -41,7 +41,6 @@ typedef enum } SESSIONLISTFILTER; int session_isvalid(MXS_SESSION *); -int session_reply(void *inst, void *session, GWBUF *data); char *session_state(mxs_session_state_t); bool session_link_dcb(MXS_SESSION *, struct dcb *); diff --git a/server/core/session.c b/server/core/session.c index d286f2507..0072c3749 100644 --- a/server/core/session.c +++ b/server/core/session.c @@ -63,6 +63,15 @@ static void session_add_to_all_list(MXS_SESSION *session); static MXS_SESSION *session_find_free(); static void session_final_free(MXS_SESSION *session); +/** + * The clientReply of the session. + * + * @param inst In reality an MXS_SESSION*. + * @param session In reality an MXS_SESSION*. + * @param data The data to send to the client. + */ +static int session_reply(MXS_FILTER *inst, MXS_FILTER_SESSION *session, GWBUF *data); + /** * @brief Initialize a session * @@ -162,8 +171,12 @@ session_alloc(SERVICE *service, DCB *client_dcb) session->head.routeQuery = (void *)(service->router->routeQuery); - session->tail.instance = session; - session->tail.session = session; + // NOTE: Here we cast the session into a MXS_FILTER and MXS_FILTER_SESSION + // NOTE: and session_reply into a filter clientReply. That's dubious but ok + // NOTE: as session_reply will know what to do. In practice, the session + // NOTE: will be called as if it would be the last filter. + session->tail.instance = (MXS_FILTER*)session; + session->tail.session = (MXS_FILTER_SESSION*)session; session->tail.clientReply = session_reply; if (SESSION_STATE_TO_BE_FREED != session->state @@ -664,14 +677,17 @@ session_setup_filters(MXS_SESSION *session) * Entry point for the final element in the upstream filter, i.e. the writing * of the data to the client. * + * Looks like a filter `clientReply`, but in this case both the instance and + * the session argument will be a MXS_SESSION*. + * * @param instance The "instance" data * @param session The session * @param data The buffer chain to write */ int -session_reply(void *instance, void *session, GWBUF *data) +session_reply(MXS_FILTER *instance, MXS_FILTER_SESSION *session, GWBUF *data) { - MXS_SESSION *the_session = (MXS_SESSION *)session; + MXS_SESSION *the_session = (MXS_SESSION*)session; return the_session->client_dcb->func.write(the_session->client_dcb, data); }