From ac14f3c7b68424250a32f62c2f3008778cfe902e Mon Sep 17 00:00:00 2001 From: Ted Ross Date: Tue, 11 Jun 2013 14:13:11 +0000 Subject: QPID_4913 - Work in progress - Added configuration handling of listeners (basic, still needs ssl, sasl, etc.) - Updated the server tests to use the configuration file rather than hard-coded settings. - Fixed a bug in the CMake file regarding the use of the PYTHON include path. - Made changes to accomodate older compilers. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1491805 13f79535-47bb-0310-9956-ffa450edef68 --- extras/dispatch/CMakeLists.txt | 2 +- extras/dispatch/etc/qpid-dispatch.conf | 117 +++++++++++++++-------- extras/dispatch/include/qpid/dispatch/dispatch.h | 5 +- extras/dispatch/include/qpid/dispatch/server.h | 18 ++-- extras/dispatch/router/src/main.c | 24 +---- extras/dispatch/src/config.c | 17 ++-- extras/dispatch/src/config_private.h | 2 +- extras/dispatch/src/dispatch.c | 70 +++++++++++--- extras/dispatch/src/dispatch_private.h | 2 + extras/dispatch/tests/CMakeLists.txt | 2 +- extras/dispatch/tests/run_unit_tests.c | 8 +- extras/dispatch/tests/server_test.c | 11 ++- extras/dispatch/tests/threads4.conf | 26 +++++ 13 files changed, 208 insertions(+), 96 deletions(-) create mode 100644 extras/dispatch/tests/threads4.conf diff --git a/extras/dispatch/CMakeLists.txt b/extras/dispatch/CMakeLists.txt index d01e6c1321..f51d25c486 100644 --- a/extras/dispatch/CMakeLists.txt +++ b/extras/dispatch/CMakeLists.txt @@ -56,7 +56,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src ${proton_include} - ${PYTHON_INCLUDE_DIRS} + ${PYTHON_INCLUDE_PATH} ) ## diff --git a/extras/dispatch/etc/qpid-dispatch.conf b/extras/dispatch/etc/qpid-dispatch.conf index d9dee9edf4..81e4f8f617 100644 --- a/extras/dispatch/etc/qpid-dispatch.conf +++ b/extras/dispatch/etc/qpid-dispatch.conf @@ -27,7 +27,7 @@ container { ## process message traffic and other application work (timers, non-amqp ## file descriptors, etc.) ## - ## The number of threads should be a function of the available + ## The number of threads should be related to the number of available ## processor cores. To fully utilize a quad-core system, set the ## number of threads to 4. ## @@ -42,6 +42,84 @@ container { container-name: Qpid.Dispatch.Router.A } + +## +## SSL Profile section - Zero or more SSL profiles may be defined here and +## then referenced later in listeners (for incoming connections) or +## connectors (for outgoing connectors). +## +ssl-profile { + ## + ## name - The name of the profile to be referenced later. + ## + name: ssl-profile-name + + ## + ## trusted-cert-db - The path to the database that contains the public + ## certificates of trusted certificate authorities (CAs). + ## + ## trusted-cert-db: /path/to/trusted-ca.db + + ## + ## cert-file - The path to the file containing the PEM-formatted public + ## certificate to be used on the local end of any connections using + ## this profile. + ## + ## cert-file: /path/to/cert-file.pem + + ## + ## key-file - The path to the file containing the PEM-formatted private + ## key for the above certificate. + ## + ## key-file: /path/to/private-key-file.pem + + ## + ## password-file - If the above private key is password protected, this + ## is the path to a file containing the password that unlocks the + ## certificate key. + ## + ## password-file: /path/to/password-file + + ## + ## password - An alternative to storing the password in a file + ## referenced by password-file is to supply the password right here in + ## the configuration file. This option can be used by supplying the + ## password in the 'password' option. Don't use both password and + ## password-file in the same profile. + ## + ## password: +} + + +## +## Listeners and Connectors +## +listener { + addr: 0.0.0.0 + port: 5672 + sasl-mechanisms: ANONYMOUS +} + +listener { + label: Router Interconnect Access + addr: 0.0.0.0 + port: 5671 + sasl-mechanisms: EXTERNAL + ssl-profile: ssl-profile-name + require-peer-auth: yes + allow-unsecured: no +} + +connector { + label: Router Uplink + host: backbone.enterprise.com + port: 5671 + sasl-mechanisms: EXTERNAL + ssl-profile: ssl-profile-name + allow-redirect: no +} + + ## ## Router section - Configure the AMQP router function. ## @@ -92,41 +170,4 @@ router { mobile-addr-max-age: 60 } -ssl-profile { - name: ssl-link - trusted-cert-db: /opt/dispatch/x.509/cert.db - cert-file: /opt/dispatch/x.509/router-cert.pem - key-file: /opt/dispatch/x.509/router-key.pem - password-file: /opt/dispatch/x.509/router-key.pass -} - - -## -## Listeners and Connectors -## -listener { - addr: 0.0.0.0 - port: 5672 - sasl-mechanisms: ANONYMOUS -} - -listener { - label: Router Interconnect Access - addr: 0.0.0.0 - port: 5671 - sasl-mechanisms: EXTERNAL - ssl-profile: ssl-link - require-peer-auth: yes - allow-unsecured: no -} - -connector { - label: Router Uplink - host: backbone.enterprise.com - port: 5671 - sasl-mechanisms: EXTERNAL - ssl-profile: ssl-link - allow-redirect: no -} - diff --git a/extras/dispatch/include/qpid/dispatch/dispatch.h b/extras/dispatch/include/qpid/dispatch/dispatch.h index e785cb6385..87f3fc32d1 100644 --- a/extras/dispatch/include/qpid/dispatch/dispatch.h +++ b/extras/dispatch/include/qpid/dispatch/dispatch.h @@ -29,9 +29,10 @@ typedef struct dx_dispatch_t dx_dispatch_t; /** * \brief Initialize the Dispatch library and prepare it for operation. * + * #param config_path The path to the configuration file. * @return A handle to be used in API calls for this instance. */ -dx_dispatch_t *dx_dispatch(); +dx_dispatch_t *dx_dispatch(const char *config_path); /** @@ -41,6 +42,8 @@ dx_dispatch_t *dx_dispatch(); */ void dx_dispatch_free(dx_dispatch_t *dispatch); +void dx_dispatch_configure(dx_dispatch_t *dispatch); + /** * @} diff --git a/extras/dispatch/include/qpid/dispatch/server.h b/extras/dispatch/include/qpid/dispatch/server.h index 7e2c56a7dc..7b2d4a2432 100644 --- a/extras/dispatch/include/qpid/dispatch/server.h +++ b/extras/dispatch/include/qpid/dispatch/server.h @@ -283,29 +283,29 @@ typedef struct dx_server_config_t { /** * Host name or network address to bind to a listener or use in the connector. */ - char *host; + const char *host; /** * Port name or number to bind to a listener or use in the connector. */ - char *port; + const char *port; /** * Space-separated list of SASL mechanisms to be accepted for the connection. */ - char *sasl_mechanisms; + const char *sasl_mechanisms; /** * If appropriate for the mechanism, the username for authentication * (connector only) */ - char *sasl_username; + const char *sasl_username; /** * If appropriate for the mechanism, the password for authentication * (connector only) */ - char *sasl_password; + const char *sasl_password; /** * If appropriate for the mechanism, the minimum acceptable security strength factor @@ -338,23 +338,23 @@ typedef struct dx_server_config_t { * Path to the file containing the PEM-formatted public certificate for the local end * of the connection. */ - char *ssl_certificate_file; + const char *ssl_certificate_file; /** * Path to the file containing the PEM-formatted private key for the local end of the * connection. */ - char *ssl_private_key_file; + const char *ssl_private_key_file; /** * The password used to sign the private key, or NULL if the key is not protected. */ - char *ssl_password; + const char *ssl_password; /** * Path to the file containing the PEM-formatted set of certificates of trusted CAs. */ - char *ssl_trusted_certificate_db; + const char *ssl_trusted_certificate_db; /** * Iff non-zero, require that the peer's certificate be supplied and that it be authentic diff --git a/extras/dispatch/router/src/main.c b/extras/dispatch/router/src/main.c index d97895208f..20c821d04f 100644 --- a/extras/dispatch/router/src/main.c +++ b/extras/dispatch/router/src/main.c @@ -76,28 +76,8 @@ static void server_signal_handler(void* context, int signum) static void startup(void *context) { - // TODO - Move this into a configuration framework - dx_server_pause(dispatch); - - static dx_server_config_t server_config; - server_config.host = "0.0.0.0"; - server_config.port = "5672"; - server_config.sasl_mechanisms = "ANONYMOUS"; - server_config.ssl_enabled = 0; - - dx_server_listen(dispatch, &server_config, 0); - - /* - static dx_server_config_t client_config; - client_config.host = "0.0.0.0"; - client_config.port = "10000"; - client_config.sasl_mechanisms = "ANONYMOUS"; - client_config.ssl_enabled = 0; - - dx_server_connect(dispatch, &client_config, 0); - */ - + dx_dispatch_configure(dispatch); dx_server_resume(dispatch); } @@ -106,7 +86,7 @@ int main(int argc, char **argv) { dx_log_set_mask(LOG_INFO | LOG_TRACE | LOG_ERROR); - dispatch = dx_dispatch(); + dispatch = dx_dispatch("../etc/qpid-dispatch.conf"); dx_server_set_signal_handler(dispatch, server_signal_handler, 0); dx_server_set_start_handler(dispatch, thread_start_handler, 0); diff --git a/extras/dispatch/src/config.c b/extras/dispatch/src/config.c index bc99d7f91c..407f2ffb4b 100644 --- a/extras/dispatch/src/config.c +++ b/extras/dispatch/src/config.c @@ -47,7 +47,7 @@ void dx_config_finalize() } -dx_config_t *dx_config(char *filename) +dx_config_t *dx_config(const char *filename) { dx_config_t *config = new_dx_config_t(); @@ -116,8 +116,9 @@ int dx_config_item_count(const dx_config_t *config, const char *section) pMethod = PyObject_GetAttrString(config->pObject, "item_count"); if (!pMethod || !PyCallable_Check(pMethod)) { dx_log(log_module, LOG_ERROR, "Problem with configuration module: No callable 'item_count'"); - if (pMethod) + if (pMethod) { Py_DECREF(pMethod); + } return 0; } @@ -128,8 +129,9 @@ int dx_config_item_count(const dx_config_t *config, const char *section) Py_DECREF(pArgs); if (pResult && PyInt_Check(pResult)) result = (int) PyInt_AsLong(pResult); - if (pResult) + if (pResult) { Py_DECREF(pResult); + } Py_DECREF(pMethod); return result; @@ -148,8 +150,9 @@ static PyObject *item_value(const dx_config_t *config, const char *section, int pMethod = PyObject_GetAttrString(config->pObject, method); if (!pMethod || !PyCallable_Check(pMethod)) { dx_log(log_module, LOG_ERROR, "Problem with configuration module: No callable '%s'", method); - if (pMethod) + if (pMethod) { Py_DECREF(pMethod); + } return 0; } @@ -179,8 +182,9 @@ const char *dx_config_item_value_string(const dx_config_t *config, const char *s strncpy(value, PyString_AsString(pResult), size + 1); } - if (pResult) + if (pResult) { Py_DECREF(pResult); + } return value; } @@ -194,8 +198,9 @@ uint32_t dx_config_item_value_int(const dx_config_t *config, const char *section if (pResult && PyLong_Check(pResult)) value = (uint32_t) PyLong_AsLong(pResult); - if (pResult) + if (pResult) { Py_DECREF(pResult); + } return value; } diff --git a/extras/dispatch/src/config_private.h b/extras/dispatch/src/config_private.h index bb114ebde0..3c95f6451f 100644 --- a/extras/dispatch/src/config_private.h +++ b/extras/dispatch/src/config_private.h @@ -23,7 +23,7 @@ void dx_config_initialize(); void dx_config_finalize(); -dx_config_t *dx_config(char *filename); +dx_config_t *dx_config(const char *filename); void dx_config_free(dx_config_t *config); #endif diff --git a/extras/dispatch/src/dispatch.c b/extras/dispatch/src/dispatch.c index 3c8fa9ba83..23199c7c99 100644 --- a/extras/dispatch/src/dispatch.c +++ b/extras/dispatch/src/dispatch.c @@ -19,10 +19,11 @@ #include "python_embedded.h" #include +#include +#include #include "dispatch_private.h" #include "alloc_private.h" #include "log_private.h" -#include "config_private.h" /** * Private Function Prototypes @@ -42,9 +43,24 @@ void dx_agent_free(dx_agent_t *agent); static const char *CONF_CONTAINER = "container"; static const char *CONF_ROUTER = "router"; +static const char *CONF_LISTENER = "listener"; -dx_dispatch_t *dx_dispatch() +typedef struct dx_config_listener_t { + DEQ_LINKS(struct dx_config_listener_t); + dx_server_config_t configuration; + dx_listener_t *listener; +} dx_config_listener_t; + + +ALLOC_DECLARE(dx_config_listener_t); +ALLOC_DEFINE(dx_config_listener_t); +DEQ_DECLARE(dx_config_listener_t, listener_list_t); + +listener_list_t listeners; + + +dx_dispatch_t *dx_dispatch(const char *config_path) { dx_dispatch_t *dx = NEW(dx_dispatch_t); @@ -57,20 +73,22 @@ dx_dispatch_t *dx_dispatch() dx_log_initialize(); dx_alloc_initialize(); + DEQ_INIT(listeners); + dx_config_initialize(); - dx_config_t *config = dx_config("../etc/qpid-dispatch.conf"); + dx->config = dx_config(config_path); - if (config) { - int count = dx_config_item_count(config, CONF_CONTAINER); + if (dx->config) { + int count = dx_config_item_count(dx->config, CONF_CONTAINER); if (count == 1) { - thread_count = dx_config_item_value_int(config, CONF_CONTAINER, 0, "worker-threads"); - container_name = dx_config_item_value_string(config, CONF_CONTAINER, 0, "container-name"); + thread_count = dx_config_item_value_int(dx->config, CONF_CONTAINER, 0, "worker-threads"); + container_name = dx_config_item_value_string(dx->config, CONF_CONTAINER, 0, "container-name"); } - count = dx_config_item_count(config, CONF_ROUTER); + count = dx_config_item_count(dx->config, CONF_ROUTER); if (count == 1) { - router_area = dx_config_item_value_string(config, CONF_ROUTER, 0, "area"); - router_id = dx_config_item_value_string(config, CONF_ROUTER, 0, "router-id"); + router_area = dx_config_item_value_string(dx->config, CONF_ROUTER, 0, "area"); + router_id = dx_config_item_value_string(dx->config, CONF_ROUTER, 0, "router-id"); } } @@ -95,14 +113,13 @@ dx_dispatch_t *dx_dispatch() dx_container_setup_agent(dx); dx_router_setup_agent(dx); - dx_config_free(config); - return dx; } void dx_dispatch_free(dx_dispatch_t *dx) { + dx_config_free(dx->config); dx_config_finalize(); dx_agent_free(dx->agent); dx_router_free(dx->router); @@ -112,3 +129,32 @@ void dx_dispatch_free(dx_dispatch_t *dx) dx_python_finalize(); } + +static void configure_connections(dx_dispatch_t *dx) +{ + int count; + + if (!dx->config) + return; + + count = dx_config_item_count(dx->config, CONF_LISTENER); + for (int i = 0; i < count; i++) { + dx_config_listener_t *l = new_dx_config_listener_t(); + memset(l, 0, sizeof(dx_config_listener_t)); + + l->configuration.host = dx_config_item_value_string(dx->config, CONF_LISTENER, i, "addr"); + l->configuration.port = dx_config_item_value_string(dx->config, CONF_LISTENER, i, "port"); + l->configuration.sasl_mechanisms = + dx_config_item_value_string(dx->config, CONF_LISTENER, i, "sasl-mechansism"); + l->configuration.ssl_enabled = 0; + + l->listener = dx_server_listen(dx, &l->configuration, l); + } +} + + +void dx_dispatch_configure(dx_dispatch_t *dx) +{ + configure_connections(dx); +} + diff --git a/extras/dispatch/src/dispatch_private.h b/extras/dispatch/src/dispatch_private.h index 699e3a2be4..ef93441776 100644 --- a/extras/dispatch/src/dispatch_private.h +++ b/extras/dispatch/src/dispatch_private.h @@ -20,6 +20,7 @@ */ #include "server_private.h" +#include "config_private.h" typedef struct dx_container_t dx_container_t; typedef struct dx_router_t dx_router_t; @@ -30,6 +31,7 @@ struct dx_dispatch_t { dx_container_t *container; dx_router_t *router; dx_agent_t *agent; + dx_config_t *config; }; #endif diff --git a/extras/dispatch/tests/CMakeLists.txt b/extras/dispatch/tests/CMakeLists.txt index 688e1de2f6..3d90f163b3 100644 --- a/extras/dispatch/tests/CMakeLists.txt +++ b/extras/dispatch/tests/CMakeLists.txt @@ -48,4 +48,4 @@ add_test(unit_tests_size_5 unit_tests_size 5) add_test(unit_tests_size_3 unit_tests_size 3) add_test(unit_tests_size_2 unit_tests_size 2) add_test(unit_tests_size_1 unit_tests_size 1) -add_test(unit_tests unit_tests) +add_test(unit_tests unit_tests ${CMAKE_CURRENT_SOURCE_DIR}/threads4.conf) diff --git a/extras/dispatch/tests/run_unit_tests.c b/extras/dispatch/tests/run_unit_tests.c index 9b0b5b100e..4b83d84b40 100644 --- a/extras/dispatch/tests/run_unit_tests.c +++ b/extras/dispatch/tests/run_unit_tests.c @@ -18,6 +18,7 @@ */ #include +#include int tool_tests(); int timer_tests(); @@ -26,11 +27,16 @@ int server_tests(); int main(int argc, char** argv) { + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + int result = 0; result += tool_tests(); result += timer_tests(); result += alloc_tests(); - result += server_tests(); + result += server_tests(argv[1]); return result; } diff --git a/extras/dispatch/tests/server_test.c b/extras/dispatch/tests/server_test.c index deb3ae78eb..525d8b6a9f 100644 --- a/extras/dispatch/tests/server_test.c +++ b/extras/dispatch/tests/server_test.c @@ -29,6 +29,7 @@ #define THREAD_COUNT 4 #define OCTET_COUNT 100 +static const char *config_file; static dx_dispatch_t *dx; static sys_mutex_t *test_lock; @@ -116,7 +117,7 @@ static char* test_start_handler(void *context) { int i; - dx = dx_dispatch(THREAD_COUNT, 0, 0, 0); + dx = dx_dispatch(config_file); expected_context = (void*) 0x00112233; stored_error[0] = 0x0; @@ -139,7 +140,7 @@ static char* test_start_handler(void *context) static char *test_server_start(void *context) { - dx = dx_dispatch(THREAD_COUNT, 0, 0, 0); + dx = dx_dispatch(config_file); dx_server_start(dx); dx_server_stop(dx); dx_dispatch_free(dx); @@ -153,7 +154,7 @@ static char* test_user_fd(void *context) int res; dx_timer_t *timer; - dx = dx_dispatch(THREAD_COUNT, 0, 0, 0); + dx = dx_dispatch(config_file); dx_server_set_user_fd_handler(dx, ufd_handler); timer = dx_timer(dx, fd_test_start, 0); dx_timer_schedule(timer, 0); @@ -190,12 +191,14 @@ static char* test_user_fd(void *context) } -int server_tests(void) +int server_tests(const char *_config_file) { int result = 0; test_lock = sys_mutex(); dx_log_set_mask(LOG_NONE); + config_file = _config_file; + TEST_CASE(test_server_start, 0); TEST_CASE(test_start_handler, 0); TEST_CASE(test_user_fd, 0); diff --git a/extras/dispatch/tests/threads4.conf b/extras/dispatch/tests/threads4.conf new file mode 100644 index 0000000000..1466e11cca --- /dev/null +++ b/extras/dispatch/tests/threads4.conf @@ -0,0 +1,26 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License +## + + +## +## Container section - Configures the general operation of the AMQP container. +## +container { + worker-threads: 4 +} -- cgit v1.2.1