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); }