Example #1
0
qd_dispatch_t *qd_dispatch(const char *python_pkgdir)
{
    qd_dispatch_t *qd = NEW(qd_dispatch_t);
    memset(qd, 0, sizeof(qd_dispatch_t));

    qd_entity_cache_initialize();   /* Must be first */
    qd_alloc_initialize();
    qd_log_initialize();
    qd_error_initialize();
    if (qd_error_code()) {
        qd_dispatch_free(qd);
        return 0;
    }

    qd_dispatch_set_router_area(qd, strdup("0"));
    qd_dispatch_set_router_id(qd, strdup("0"));
    qd->router_mode = QD_ROUTER_MODE_ENDPOINT;

    qd_python_initialize(qd, python_pkgdir);
    if (qd_error_code()) {
        qd_dispatch_free(qd);
        return 0;
    }
    qd_message_initialize();
    if (qd_error_code()) {
        qd_dispatch_free(qd);
        return 0;
    }
    qd->dl_handle = 0;
    return qd;
}
Example #2
0
int main(int argc, char** argv)
{
    if (argc != 2) {
        fprintf(stderr, "usage: %s <config-file>\n", argv[0]);
        exit(1);
    }
    int result = 0;

    // Call qd_dispatch() first initialize allocator used by other tests.
    qd_dispatch_t *qd = qd_dispatch(0);
    qd_dispatch_load_config(qd, argv[1]);
    if (qd_error_code()) {
        printf("Config failed: %s\n", qd_error_message());
        return 1;
    }
    result += timer_tests();
    result += server_tests(qd);
    result += tool_tests();
    result += parse_tests();
    result += compose_tests();
#if USE_MEMORY_POOL
    result += alloc_tests();
#endif
    result += policy_tests();
    qd_dispatch_free(qd);       // dispatch_free last.

    return result;
}
Example #3
0
qd_error_t qd_error_py_impl(const char *file, int line) {
    qd_python_check_lock();
    if (PyErr_Occurred()) {
        PyObject *type, *value, *trace;
        PyErr_Fetch(&type, &value, &trace); /* Note clears the python error indicator */

        PyObject *py_type_name = type ? PyObject_GetAttrString(type, "__name__") : NULL;
        const char *type_name = py_type_name ? PyString_AsString(py_type_name) : NULL;

        PyObject *py_value_str = value ? PyObject_Str(value) : NULL;
        const char *value_str = py_value_str ? PyString_AsString(py_value_str) : NULL;
        if (!value_str) value_str = "Unknown";

        PyErr_Clear(); /* Ignore errors while we're trying to build the values. */
        if (type_name)
            qd_error_impl(QD_ERROR_PYTHON, file, line, "%s: %s", type_name, value_str);
        else
            qd_error_impl(QD_ERROR_PYTHON, file, line, "%s", value_str);
        Py_XDECREF(py_value_str);
        Py_XDECREF(py_type_name);

        log_trace_py(type, value, trace, QD_LOG_ERROR, file, line);

        Py_XDECREF(type);
        Py_XDECREF(value);
        Py_XDECREF(trace);
    } else {
        qd_error_clear();
    }
    return qd_error_code();
}
Example #4
0
static int IoAdapter_init(IoAdapter *self, PyObject *args, PyObject *kwds)
{
    PyObject *addr;
    char aclass    = 'L';
    char phase     = '0';
    int  treatment = QD_TREATMENT_ANYCAST_CLOSEST;
    if (!PyArg_ParseTuple(args, "OO|cci", &self->handler, &addr, &aclass, &phase, &treatment))
        return -1;
    if (!PyCallable_Check(self->handler)) {
        PyErr_SetString(PyExc_TypeError, "IoAdapter.__init__ handler is not callable");
        return -1;
    }
    if (treatment == QD_TREATMENT_ANYCAST_BALANCED) {
        PyErr_SetString(PyExc_TypeError, "IoAdapter: ANYCAST_BALANCED is not supported for in-process subscriptions");
        return -1;
    }
    Py_INCREF(self->handler);
    self->qd   = dispatch;
    self->core = qd_router_core(self->qd);
    const char *address = PyString_AsString(addr);
    if (!address) return -1;
    qd_error_clear();
    self->sub = qdr_core_subscribe(self->core, address, aclass, phase, treatment, qd_io_rx_handler, self);
    if (qd_error_code()) {
        PyErr_SetString(PyExc_RuntimeError, qd_error_message());
        return -1;
    }
    return 0;
}
Example #5
0
long qd_entity_opt_long(qd_entity_t *entity, const char* attribute, long default_value) {
    if (qd_entity_has(entity, attribute)) {
        long result = qd_entity_get_long(entity, attribute);
        if (!qd_error_code())
            return result;
    }
    return default_value;
}
Example #6
0
bool qd_entity_opt_bool(qd_entity_t *entity, const char* attribute, bool default_value) {
    if (qd_entity_has(entity, attribute)) {
        bool result = qd_entity_get_bool(entity, attribute);
        if (!qd_error_code())
            return result;
    }
    return default_value;
}
Example #7
0
qd_error_t qd_dispatch_prepare(qd_dispatch_t *qd)
{
    qd->server             = qd_server(qd, qd->thread_count, qd->router_id, qd->sasl_config_path, qd->sasl_config_name);
    qd->container          = qd_container(qd);
    qd->router             = qd_router(qd, qd->router_mode, qd->router_area, qd->router_id);
    qd->connection_manager = qd_connection_manager(qd);
    qd->policy             = qd_policy(qd);
    return qd_error_code();
}
Example #8
0
/** Update the statistics in qdrouterd.conf["policy"]
 * @param[in] entity pointer to the policy management object
 **/
qd_error_t qd_entity_refresh_policy(qd_entity_t* entity, void *unused) {
    // Return global stats
    if (!qd_entity_set_long(entity, "connectionsProcessed", n_processed) &&
        !qd_entity_set_long(entity, "connectionsDenied", n_denied) &&
        !qd_entity_set_long(entity, "connectionsCurrent", n_connections)
    )
        return QD_ERROR_NONE;
    return qd_error_code();
}
Example #9
0
qd_error_t qd_policy_c_counts_refresh(long ccounts, qd_entity_t *entity)
{
    qd_policy_denial_counts_t *dc = (qd_policy_denial_counts_t*)ccounts;
    if (!qd_entity_set_long(entity, "sessionDenied", dc->sessionDenied) &&
        !qd_entity_set_long(entity, "senderDenied", dc->senderDenied) &&
        !qd_entity_set_long(entity, "receiverDenied", dc->receiverDenied)
    )
        return QD_ERROR_NONE;
    return qd_error_code();
}
Example #10
0
static void check(int fd) {
    if (qd_error_code()) {
        qd_log(log_source, QD_LOG_CRITICAL, "Router start-up failed: %s", qd_error_message());
        #ifdef __sun
        FILE *file = fdopen(fd, "a+");
        fprintf(file, "%s: %s\n", argv0, qd_error_message());
        #else
        dprintf(fd, "%s: %s\n", argv0, qd_error_message());
        #endif
        close(fd);
        exit(1);
    }
}
Example #11
0
qd_error_t qd_dispatch_load_config(qd_dispatch_t *qd, const char *config_path)
{
    qd->dl_handle = dlopen(QPID_DISPATCH_LIB, RTLD_LAZY | RTLD_NOLOAD);
    if (!qd->dl_handle)
        return qd_error(QD_ERROR_RUNTIME, "Cannot locate library %s", QPID_DISPATCH_LIB);

    qd_python_lock_state_t lock_state = qd_python_lock();
    PyObject *module = PyImport_ImportModule("qpid_dispatch_internal.management.config");
    PyObject *configure_dispatch = module ? PyObject_GetAttrString(module, "configure_dispatch") : NULL;
    Py_XDECREF(module);
    PyObject *result = configure_dispatch ? PyObject_CallFunction(configure_dispatch, "(lls)", (long)qd, qd->dl_handle, config_path) : NULL;
    Py_XDECREF(configure_dispatch);
    if (!result) qd_error_py();
    Py_XDECREF(result);
    qd_python_unlock(lock_state);
    return qd_error_code();
}
Example #12
0
// Get events in the add/remove cache into a python list of (action, type, pointer)
// Locks the entity cache so entities can be updated safely (prevent entities from being deleted.)
// Do not processs any entities if return error code != 0
// Must call qd_entity_refresh_end when done, regardless of error code.
qd_error_t qd_entity_refresh_begin(PyObject *list) {
    if (!event_lock) return QD_ERROR_NONE;    /* Unit tests don't call qd_entity_cache_initialize */
    qd_error_clear();
    sys_mutex_lock(event_lock);
    entity_event_t *event = DEQ_HEAD(event_list);
    while (event) {
        PyObject *tuple = Py_BuildValue("(isl)", (int)event->action, event->type, (long)event->object);
        if (!tuple) { qd_error_py(); break; }
        int err = PyList_Append(list, tuple);
        Py_DECREF(tuple);
        if (err) { qd_error_py(); break; }
        DEQ_REMOVE_HEAD(event_list);
        free(event);
        event = DEQ_HEAD(event_list);
    }
    return qd_error_code();
}
Example #13
0
qd_error_t qd_entity_configure_policy(qd_policy_t *policy, qd_entity_t *entity)
{
    policy->max_connection_limit = qd_entity_opt_long(entity, "maximumConnections", 0); CHECK();
    if (policy->max_connection_limit < 0)
        return qd_error(QD_ERROR_CONFIG, "maximumConnections must be >= 0");
    policy->policyFolder =
        qd_entity_opt_string(entity, "policyFolder", 0); CHECK();
    policy->enableAccessRules = qd_entity_opt_bool(entity, "enableAccessRules", false); CHECK();
    qd_log(policy->log_source, QD_LOG_INFO, "Policy configured maximumConnections: %d, policyFolder: '%s', access rules enabled: '%s'",
           policy->max_connection_limit, policy->policyFolder, (policy->enableAccessRules ? "true" : "false"));
    return QD_ERROR_NONE;

error:
    if (policy->policyFolder)
        free(policy->policyFolder);
    qd_policy_free(policy);
    return qd_error_code();
}
Example #14
0
qd_error_t qd_entity_refresh_connector(qd_entity_t* entity, void *impl)
{
    qd_connector_t *ct = (qd_connector_t*) impl;

    if (DEQ_SIZE(ct->conn_info_list) > 1) {
        qd_failover_item_list_t   conn_info_list = ct->conn_info_list;

        qd_failover_item_t *item = DEQ_HEAD(conn_info_list);

        //
        // As you can see we are skipping the head of the list. The
        // first item in the list is always the original connection information
        // and we dont want to display that information as part of the failover list.
        //
        int arr_length = get_failover_info_length(conn_info_list);
        char failover_info[arr_length];
        memset(failover_info, 0, sizeof(failover_info));

        item = DEQ_NEXT(item);

        while(item) {
            if (item->scheme) {
                strcat(failover_info, item->scheme);
                strcat(failover_info, "://");
            }
            if (item->host_port) {
                strcat(failover_info, item->host_port);
            }
            item = DEQ_NEXT(item);
            if (item) {
                strcat(failover_info, ", ");
            }
        }

        if (qd_entity_set_string(entity, "failoverList", failover_info) == 0)
            return QD_ERROR_NONE;
    }
    else {
        if (qd_entity_clear(entity, "failoverList") == 0)
            return QD_ERROR_NONE;
    }

    return qd_error_code();
}
Example #15
0
// Copy a message field, using to_py to a python object attribute.
static qd_error_t iter_to_py_attr(qd_field_iterator_t *iter,
                                  PyObject* (*to_py)(qd_field_iterator_t *),
                                  PyObject *obj, const char *attr)
{
    qd_error_clear();
    if (iter) {
        PyObject *value = to_py(iter);
        qd_field_iterator_free(iter);
        if (value) {
            PyObject_SetAttrString(obj, attr, value);
            Py_DECREF(value);
        }
        else {
            qd_error_py();      /* In case there were python errors. */
            qd_error(QD_ERROR_MESSAGE, "Can't convert message field %s", attr);
        }
    }
    return qd_error_code();
}
Example #16
0
qd_error_t qd_error_errno_impl(int errnum, const char *file, int line, const char *fmt, ...) {
    if (errnum) {
        ts.error_code = QD_ERROR_SYSTEM;
        char buf[ERROR_MAX];
        char *errstr = strerror_r(errno, buf, sizeof(buf));

        char *begin = ts.error_message;
        char *end = begin + ERROR_MAX;
        va_list arglist;
        va_start(arglist, fmt);
        vaprintf(&begin, end, fmt, arglist);
        va_end(arglist);
        aprintf(&begin, end, ": %s", errstr);
        qd_log_impl(log_source, QD_LOG_ERROR, file, line, "%s", qd_error_message());
        return qd_error_code();
    }
    else
        return qd_error_clear();
}
Example #17
0
static qd_error_t compose_python_message(qd_composed_field_t **field, PyObject *message,
                                         qd_dispatch_t* qd) {
    *field = qd_compose(QD_PERFORMATIVE_PROPERTIES, *field);
    qd_compose_start_list(*field);
    qd_compose_insert_null(*field);                                 // message-id
    qd_compose_insert_null(*field);                                 // user-id
    qd_py_attr_to_composed(message, "address", *field); QD_ERROR_RET(); // to
    qd_compose_insert_null(*field);                                 // subject
    qd_compose_insert_null(*field);                                 // reply-to
    qd_py_attr_to_composed(message, "correlation_id", *field); QD_ERROR_RET(); // correlation-id
    qd_compose_end_list(*field);

    *field = qd_compose(QD_PERFORMATIVE_APPLICATION_PROPERTIES, *field);  QD_ERROR_RET();
    qd_py_attr_to_composed(message, "properties", *field); QD_ERROR_RET();

    *field = qd_compose(QD_PERFORMATIVE_BODY_AMQP_VALUE, *field); QD_ERROR_RET();
    qd_py_attr_to_composed(message, "body", *field); QD_ERROR_RET();
    return qd_error_code();
}
Example #18
0
qd_error_t qd_log_entity(qd_entity_t *entity) {

    qd_error_clear();
    char* module = qd_entity_get_string(entity, "module"); QD_ERROR_RET();
    sys_mutex_lock(log_source_lock);
    qd_log_source_t *src = qd_log_source_lh(module); /* The original log source */
    free(module);
    qd_log_source_t copy = *src; /* A copy to modify outside the lock. */
    sys_mutex_unlock(log_source_lock);

    if (qd_entity_has(entity, "enable")) {
        char *enable = qd_entity_get_string(entity, "enable");
        copy.mask = enable_mask(enable);
        free(enable);
    }
    QD_ERROR_RET();

    if (qd_entity_has(entity, "timestamp"))
        copy.timestamp = qd_entity_get_bool(entity, "timestamp");
    QD_ERROR_RET();

    if (qd_entity_has(entity, "source"))
        copy.source = qd_entity_get_bool(entity, "source");
    QD_ERROR_RET();

    if (qd_entity_has(entity, "output")) {
         log_sink_free_lh(copy.sink); /* DEFAULT source may already have a sink */
        char* output = qd_entity_get_string(entity, "output"); QD_ERROR_RET();
        copy.sink = log_sink_lh(output);
        free(output);
        if (copy.sink->syslog) /* Timestamp off for syslog. */
            copy.timestamp = 0;
    }

    sys_mutex_lock(log_source_lock);
    *src = copy;
    sys_mutex_unlock(log_source_lock);
    return qd_error_code();
}
Example #19
0
static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity, bool is_listener)
{
    qd_error_clear();

    bool authenticatePeer   = qd_entity_opt_bool(entity, "authenticatePeer",  false);    CHECK();
    bool verifyHostName     = qd_entity_opt_bool(entity, "verifyHostName",    true);     CHECK();
    bool requireEncryption  = qd_entity_opt_bool(entity, "requireEncryption", false);    CHECK();
    bool requireSsl         = qd_entity_opt_bool(entity, "requireSsl",        false);    CHECK();

    memset(config, 0, sizeof(*config));
    config->log_message          = qd_entity_opt_string(entity, "logMessage", 0);     CHECK();
    config->log_bits             = populate_log_message(config);
    config->port                 = qd_entity_get_string(entity, "port");              CHECK();
    config->name                 = qd_entity_opt_string(entity, "name", 0);           CHECK();
    config->role                 = qd_entity_get_string(entity, "role");              CHECK();
    config->inter_router_cost    = qd_entity_opt_long(entity, "cost", 1);             CHECK();
    config->protocol_family      = qd_entity_opt_string(entity, "protocolFamily", 0); CHECK();
    config->http                 = qd_entity_opt_bool(entity, "http", false);         CHECK();
    config->http_root            = qd_entity_opt_string(entity, "httpRoot", false);   CHECK();
    config->http = config->http || config->http_root; /* httpRoot implies http */
    config->max_frame_size       = qd_entity_get_long(entity, "maxFrameSize");        CHECK();
    config->max_sessions         = qd_entity_get_long(entity, "maxSessions");         CHECK();
    uint64_t ssn_frames          = qd_entity_opt_long(entity, "maxSessionFrames", 0); CHECK();
    config->idle_timeout_seconds = qd_entity_get_long(entity, "idleTimeoutSeconds");  CHECK();
    if (is_listener) {
        config->initial_handshake_timeout_seconds = qd_entity_get_long(entity, "initialHandshakeTimeoutSeconds");  CHECK();
    }
    config->sasl_username        = qd_entity_opt_string(entity, "saslUsername", 0);   CHECK();
    config->sasl_password        = qd_entity_opt_string(entity, "saslPassword", 0);   CHECK();
    config->sasl_mechanisms      = qd_entity_opt_string(entity, "saslMechanisms", 0); CHECK();
    config->ssl_profile          = qd_entity_opt_string(entity, "sslProfile", 0);     CHECK();
    config->sasl_plugin          = qd_entity_opt_string(entity, "saslPlugin", 0);   CHECK();
    config->link_capacity        = qd_entity_opt_long(entity, "linkCapacity", 0);     CHECK();
    config->multi_tenant         = qd_entity_opt_bool(entity, "multiTenant", false);  CHECK();
    set_config_host(config, entity);

    //
    // Handle the defaults for various settings
    //
    if (config->link_capacity == 0)
        config->link_capacity = 250;

    if (config->max_sessions == 0 || config->max_sessions > 32768)
        // Proton disallows > 32768
        config->max_sessions = 32768;

    if (config->max_frame_size < QD_AMQP_MIN_MAX_FRAME_SIZE)
        // Silently promote the minimum max-frame-size
        // Proton will do this but the number is needed for the
        // incoming capacity calculation.
        config->max_frame_size = QD_AMQP_MIN_MAX_FRAME_SIZE;

    //
    // Given session frame count and max frame size compute session incoming_capacity
    //
    if (ssn_frames == 0)
        config->incoming_capacity = (sizeof(size_t) < 8) ? 0x7FFFFFFFLL : 0x7FFFFFFFLL * config->max_frame_size;
    else {
        uint64_t mfs      = (uint64_t) config->max_frame_size;
        uint64_t trial_ic = ssn_frames * mfs;
        uint64_t limit    = (sizeof(size_t) < 8) ? (1ll << 31) - 1 : 0;
        if (limit == 0 || trial_ic < limit) {
            // Silently promote incoming capacity of zero to one
            config->incoming_capacity = 
                (trial_ic < QD_AMQP_MIN_MAX_FRAME_SIZE ? QD_AMQP_MIN_MAX_FRAME_SIZE : trial_ic);
        } else {
            config->incoming_capacity = limit;
            uint64_t computed_ssn_frames = limit / mfs;
            qd_log(qd->connection_manager->log_source, QD_LOG_WARNING,
                   "Server configuation for I/O adapter entity name:'%s', host:'%s', port:'%s', "
                   "requested maxSessionFrames truncated from %"PRId64" to %"PRId64,
                   config->name, config->host, config->port, ssn_frames, computed_ssn_frames);
        }
    }

    //
    // For now we are hardwiring this attribute to true.  If there's an outcry from the
    // user community, we can revisit this later.
    //
    config->allowInsecureAuthentication = true;
    config->verify_host_name = verifyHostName;

    char *stripAnnotations  = qd_entity_opt_string(entity, "stripAnnotations", 0);
    load_strip_annotations(config, stripAnnotations);
    free(stripAnnotations);
    stripAnnotations = 0;
    CHECK();

    config->requireAuthentication = authenticatePeer;
    config->requireEncryption     = requireEncryption || requireSsl;

    if (config->ssl_profile) {
        config->ssl_required = requireSsl;
        config->ssl_require_peer_authentication = config->sasl_mechanisms &&
            strstr(config->sasl_mechanisms, "EXTERNAL") != 0;

        qd_config_ssl_profile_t *ssl_profile =
            qd_find_ssl_profile(qd->connection_manager, config->ssl_profile);
        if (ssl_profile) {
            config->ssl_certificate_file = SSTRDUP(ssl_profile->ssl_certificate_file);
            config->ssl_private_key_file = SSTRDUP(ssl_profile->ssl_private_key_file);
            config->ciphers = SSTRDUP(ssl_profile->ciphers);
            config->ssl_password = SSTRDUP(ssl_profile->ssl_password);
            config->ssl_trusted_certificate_db = SSTRDUP(ssl_profile->ssl_trusted_certificate_db);
            config->ssl_trusted_certificates = SSTRDUP(ssl_profile->ssl_trusted_certificates);
            config->ssl_uid_format = SSTRDUP(ssl_profile->ssl_uid_format);
            config->ssl_display_name_file = SSTRDUP(ssl_profile->ssl_display_name_file);
        }
    }

    if (config->sasl_plugin) {
        qd_config_sasl_plugin_t *sasl_plugin =
            qd_find_sasl_plugin(qd->connection_manager, config->sasl_plugin);
        if (sasl_plugin) {
            config->auth_service = SSTRDUP(sasl_plugin->auth_service);
            config->sasl_init_hostname = SSTRDUP(sasl_plugin->sasl_init_hostname);
            qd_log(qd->connection_manager->log_source, QD_LOG_INFO, "Using auth service %s from  SASL Plugin %s", config->auth_service, config->sasl_plugin);

            if (sasl_plugin->auth_ssl_profile) {
                qd_config_ssl_profile_t *auth_ssl_profile =
                    qd_find_ssl_profile(qd->connection_manager, sasl_plugin->auth_ssl_profile);
                config->auth_ssl_conf = pn_ssl_domain(PN_SSL_MODE_CLIENT);

                if (auth_ssl_profile->ssl_certificate_file) {
                    if (pn_ssl_domain_set_credentials(config->auth_ssl_conf,
                                                      auth_ssl_profile->ssl_certificate_file,
                                                      auth_ssl_profile->ssl_private_key_file,
                                                      auth_ssl_profile->ssl_password)) {
                        qd_error(QD_ERROR_RUNTIME, "Cannot set SSL credentials for authentication service"); CHECK();
                    }
                }
                if (auth_ssl_profile->ssl_trusted_certificate_db) {
                    if (pn_ssl_domain_set_trusted_ca_db(config->auth_ssl_conf, auth_ssl_profile->ssl_trusted_certificate_db)) {
                        qd_error(QD_ERROR_RUNTIME, "Cannot set trusted SSL certificate db for authentication service" ); CHECK();
                    } else {
                        if (pn_ssl_domain_set_peer_authentication(config->auth_ssl_conf, PN_SSL_VERIFY_PEER, auth_ssl_profile->ssl_trusted_certificate_db)) {
                            qd_error(QD_ERROR_RUNTIME, "Cannot set SSL peer verification for authentication service"); CHECK();
                        }
                    }
                }
                if (auth_ssl_profile->ciphers) {
                    if (pn_ssl_domain_set_ciphers(config->auth_ssl_conf, auth_ssl_profile->ciphers)) {
                        return qd_error(QD_ERROR_RUNTIME, "Cannot set ciphers. The ciphers string might be invalid. Use openssl ciphers -v <ciphers> to validate");
                    }
                }

            }
        } else {
            qd_error(QD_ERROR_RUNTIME, "Cannot find sasl plugin %s", config->sasl_plugin); CHECK();
        }
    }

    return QD_ERROR_NONE;

  error:
    qd_server_config_free(config);
    return qd_error_code();
}
static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity)
{
    qd_error_clear();

    bool authenticatePeer   = qd_entity_opt_bool(entity, "authenticatePeer",  false); CHECK();
    char *stripAnnotations  = qd_entity_opt_string(entity, "stripAnnotations", 0);    CHECK();
    bool requireEncryption  = qd_entity_opt_bool(entity, "requireEncryption", false); CHECK();
    bool requireSsl         = qd_entity_opt_bool(entity, "requireSsl",        false); CHECK();
    bool depRequirePeerAuth = qd_entity_opt_bool(entity, "requirePeerAuth",   false); CHECK();
    bool depAllowUnsecured  = qd_entity_opt_bool(entity, "allowUnsecured", !requireSsl); CHECK();

    memset(config, 0, sizeof(*config));
    config->host                 = qd_entity_get_string(entity, "addr"); CHECK();
    config->port                 = qd_entity_get_string(entity, "port"); CHECK();
    config->name                 = qd_entity_opt_string(entity, "name", 0); CHECK();
    config->role                 = qd_entity_get_string(entity, "role"); CHECK();
    config->protocol_family      = qd_entity_opt_string(entity, "protocolFamily", 0); CHECK();
    config->max_frame_size       = qd_entity_get_long(entity, "maxFrameSize"); CHECK();
    config->idle_timeout_seconds = qd_entity_get_long(entity, "idleTimeoutSeconds"); CHECK();
    config->sasl_username        = qd_entity_opt_string(entity, "saslUsername", 0); CHECK();
    config->sasl_password        = qd_entity_opt_string(entity, "saslPassword", 0); CHECK();
    config->sasl_mechanisms      = qd_entity_opt_string(entity, "saslMechanisms", 0); CHECK();
    config->ssl_enabled          = has_attrs(entity, ssl_attributes, ssl_attributes_count);
    config->link_capacity        = qd_entity_opt_long(entity, "linkCapacity", 0); CHECK();

    //
    // Handle the defaults for link capacity.
    //
    if (config->link_capacity == 0) {
        if (strcmp("inter-router", config->role) == 0)
            config->link_capacity = 100000; // This is effectively infinite since session flow control will be more stringent.
        else
            config->link_capacity = 250;
    }

    //
    // For now we are hardwiring this attribute to true.  If there's an outcry from the
    // user community, we can revisit this later.
    //
    config->allowInsecureAuthentication = true;

    load_strip_annotations(config, stripAnnotations);

    config->requireAuthentication = authenticatePeer || depRequirePeerAuth;
    config->requireEncryption     = requireEncryption || !depAllowUnsecured;

    if (config->ssl_enabled) {
        config->ssl_required = requireSsl || !depAllowUnsecured;
        config->ssl_require_peer_authentication = config->sasl_mechanisms &&
            strstr(config->sasl_mechanisms, "EXTERNAL") != 0;
        config->ssl_certificate_file =
            qd_entity_opt_string(entity, "certFile", 0); CHECK();
        config->ssl_private_key_file =
            qd_entity_opt_string(entity, "keyFile", 0); CHECK();
        config->ssl_password =
            qd_entity_opt_string(entity, "password", 0); CHECK();
        config->ssl_trusted_certificate_db =
            qd_entity_opt_string(entity, "certDb", 0); CHECK();
        config->ssl_trusted_certificates =
            qd_entity_opt_string(entity, "trustedCerts", 0); CHECK();
        config->ssl_uid_format =
            qd_entity_opt_string(entity, "uidFormat", 0); CHECK();
        config->ssl_display_name_file =
            qd_entity_opt_string(entity, "displayNameFile", 0); CHECK();
    }

    free(stripAnnotations);
    return QD_ERROR_NONE;

  error:
    qd_server_config_free(config);
    return qd_error_code();
}
Example #21
0
qd_error_t qd_dispatch_configure_auto_link(qd_dispatch_t *qd, qd_entity_t *entity) {
    if (!qd->router) return qd_error(QD_ERROR_NOT_FOUND, "No router available");
    qd_router_configure_auto_link(qd->router, entity);
    return qd_error_code();
}
Example #22
0
static qd_error_t load_server_config(qd_dispatch_t *qd, qd_server_config_t *config, qd_entity_t* entity, qd_config_ssl_profile_t **ssl_profile)
{
    qd_error_clear();

    bool authenticatePeer   = qd_entity_opt_bool(entity, "authenticatePeer",  false);    CHECK();
    bool verifyHostName     = qd_entity_opt_bool(entity, "verifyHostName",    true);     CHECK();
    char *stripAnnotations  = qd_entity_opt_string(entity, "stripAnnotations", 0);       CHECK();
    bool requireEncryption  = qd_entity_opt_bool(entity, "requireEncryption", false);    CHECK();
    bool requireSsl         = qd_entity_opt_bool(entity, "requireSsl",        false);    CHECK();
    bool depRequirePeerAuth = qd_entity_opt_bool(entity, "requirePeerAuth",   false);    CHECK();
    bool depAllowUnsecured  = qd_entity_opt_bool(entity, "allowUnsecured", !requireSsl); CHECK();

    memset(config, 0, sizeof(*config));
    config->port                 = qd_entity_get_string(entity, "port");              CHECK();
    config->name                 = qd_entity_opt_string(entity, "name", 0);           CHECK();
    config->role                 = qd_entity_get_string(entity, "role");              CHECK();
    config->inter_router_cost    = qd_entity_opt_long(entity, "cost", 1);             CHECK();
    config->protocol_family      = qd_entity_opt_string(entity, "protocolFamily", 0); CHECK();
    config->max_frame_size       = qd_entity_get_long(entity, "maxFrameSize");        CHECK();
    config->max_sessions         = qd_entity_get_long(entity, "maxSessions");         CHECK();
    uint64_t ssn_frames          = qd_entity_get_long(entity, "maxSessionFrames");    CHECK();
    config->idle_timeout_seconds = qd_entity_get_long(entity, "idleTimeoutSeconds");  CHECK();
    config->sasl_username        = qd_entity_opt_string(entity, "saslUsername", 0);   CHECK();
    config->sasl_password        = qd_entity_opt_string(entity, "saslPassword", 0);   CHECK();
    config->sasl_mechanisms      = qd_entity_opt_string(entity, "saslMechanisms", 0); CHECK();
    config->ssl_profile          = qd_entity_opt_string(entity, "sslProfile", 0);     CHECK();
    config->link_capacity        = qd_entity_opt_long(entity, "linkCapacity", 0);     CHECK();
    set_config_host(config, entity);

    //
    // Handle the defaults for various settings
    //
    if (config->link_capacity == 0)
        config->link_capacity = 250;

    if (config->max_sessions == 0 || config->max_sessions > 32768)
        // Proton disallows > 32768
        config->max_sessions = 32768;

    if (config->max_frame_size < QD_AMQP_MIN_MAX_FRAME_SIZE)
        // Silently promote the minimum max-frame-size
        // Proton will do this but the number is needed for the
        // incoming capacity calculation.
        config->max_frame_size = QD_AMQP_MIN_MAX_FRAME_SIZE;

    //
    // Given session frame count and max frame size compute session incoming_capacity
    // Limit total capacity to 2^31-1.
    // 
    uint64_t mfs      = (uint64_t)config->max_frame_size;
    uint64_t trial_ic = ssn_frames * mfs;
    uint64_t limit    = (1ll << 31) - 1;
    if (trial_ic < limit) {
        // Silently promote incoming capacity of zero to one
        config->incoming_capacity = 
            (trial_ic < QD_AMQP_MIN_MAX_FRAME_SIZE ? QD_AMQP_MIN_MAX_FRAME_SIZE : trial_ic);
    } else {
        config->incoming_capacity = limit;
        uint64_t computed_ssn_frames = limit / mfs;
        qd_log(qd->connection_manager->log_source, QD_LOG_WARNING,
               "Server configuation for I/O adapter entity name:'%s', host:'%s', port:'%s', "
               "requested maxSessionFrames truncated from %llu to %llu",
               config->name, config->host, config->port, ssn_frames, computed_ssn_frames);
    }

    //
    // For now we are hardwiring this attribute to true.  If there's an outcry from the
    // user community, we can revisit this later.
    //
    config->allowInsecureAuthentication = true;
    config->verify_host_name = verifyHostName;

    load_strip_annotations(config, stripAnnotations);

    config->requireAuthentication = authenticatePeer || depRequirePeerAuth;
    config->requireEncryption     = requireEncryption || !depAllowUnsecured;


    if (config->ssl_profile) {
        config->ssl_required = requireSsl || !depAllowUnsecured;
        config->ssl_require_peer_authentication = config->sasl_mechanisms &&
            strstr(config->sasl_mechanisms, "EXTERNAL") != 0;

        *ssl_profile = qd_find_ssl_profile(qd->connection_manager, config->ssl_profile);
        if (*ssl_profile) {
            config->ssl_certificate_file = (*ssl_profile)->ssl_certificate_file;
            config->ssl_private_key_file = (*ssl_profile)->ssl_private_key_file;
            config->ssl_password = (*ssl_profile)->ssl_password;
            config->ssl_trusted_certificate_db = (*ssl_profile)->ssl_trusted_certificate_db;
            config->ssl_trusted_certificates = (*ssl_profile)->ssl_trusted_certificates;
            config->ssl_uid_format = (*ssl_profile)->ssl_uid_format;
            config->ssl_display_name_file = (*ssl_profile)->ssl_display_name_file;
        }
        sys_atomic_inc(&(*ssl_profile)->ref_count);
    }

    free(stripAnnotations);
    return QD_ERROR_NONE;

  error:
    qd_server_config_free(config);
    return qd_error_code();
}
Example #23
0
qd_error_t qd_py_to_composed(PyObject *value, qd_composed_field_t *field)
{
    qd_python_check_lock();
    qd_error_clear();
    if (value == Py_None) {
        qd_compose_insert_null(field);
    }
    else if (PyBool_Check(value)) {
        qd_compose_insert_bool(field, PyInt_AS_LONG(value) ? 1 : 0);
    }
    else if (PyInt_Check(value)) {
        qd_compose_insert_long(field, (int64_t) PyInt_AS_LONG(value));
    }
    else if (PyLong_Check(value)) {
        qd_compose_insert_long(field, (int64_t) PyLong_AsLongLong(value));
    }
    else if (PyString_Check(value) || PyUnicode_Check(value)) {
        qd_compose_insert_string(field, PyString_AsString(value));
    }
    else if (PyDict_Check(value)) {
        Py_ssize_t  iter = 0;
        PyObject   *key;
        PyObject   *val;
        qd_compose_start_map(field);
        while (PyDict_Next(value, &iter, &key, &val)) {
            qd_py_to_composed(key, field); QD_ERROR_RET();
            qd_py_to_composed(val, field); QD_ERROR_RET();
        }
        QD_ERROR_PY_RET();
        qd_compose_end_map(field);
    }

    else if (PyList_Check(value)) {
        Py_ssize_t count = PyList_Size(value);
        if (count == 0)
            qd_compose_empty_list(field);
        else {
            qd_compose_start_list(field);
            for (Py_ssize_t idx = 0; idx < count; idx++) {
                PyObject *item = PyList_GetItem(value, idx); QD_ERROR_PY_RET();
                qd_py_to_composed(item, field); QD_ERROR_RET();
            }
            qd_compose_end_list(field);
        }
    }

    else if (PyTuple_Check(value)) {
        Py_ssize_t count = PyTuple_Size(value);
        if (count == 0)
            qd_compose_empty_list(field);
        else {
            qd_compose_start_list(field);
            for (Py_ssize_t idx = 0; idx < count; idx++) {
                PyObject *item = PyTuple_GetItem(value, idx); QD_ERROR_PY_RET();
                qd_py_to_composed(item, field); QD_ERROR_RET();
            }
            qd_compose_end_list(field);
        }
    }
    else {
        PyObject *type=0, *typestr=0, *repr=0;
        if ((type = PyObject_Type(value)) &&
            (typestr = PyObject_Str(type)) &&
            (repr = PyObject_Repr(value)))
            qd_error(QD_ERROR_TYPE, "Can't compose object of type %s: %s",
                     PyString_AsString(typestr), PyString_AsString(repr));
        else
            qd_error(QD_ERROR_TYPE, "Can't compose python object of unknown type");

        Py_XDECREF(type);
        Py_XDECREF(typestr);
        Py_XDECREF(repr);
    }
    return qd_error_code();
}
Example #24
0
qd_error_t qd_router_python_setup(qd_router_t *router)
{
    qd_error_clear();
    log_source = qd_log_source("ROUTER");

    qdr_core_route_table_handlers(router->router_core,
                                  router,
                                  qd_router_mobile_added,
                                  qd_router_mobile_removed,
                                  qd_router_link_lost);

    //
    // If we are not operating as an interior router, don't start the
    // router module.
    //
    if (router->router_mode != QD_ROUTER_MODE_INTERIOR)
        return QD_ERROR_NONE;

    PyObject *pDispatchModule = qd_python_module();
    RouterAdapterType.tp_new = PyType_GenericNew;
    PyType_Ready(&RouterAdapterType);
    QD_ERROR_PY_RET();

    PyTypeObject *raType = &RouterAdapterType;
    Py_INCREF(raType);
    PyModule_AddObject(pDispatchModule, "RouterAdapter", (PyObject*) &RouterAdapterType);

    //
    // Attempt to import the Python Router module
    //
    PyObject* pId;
    PyObject* pArea;
    PyObject* pMaxRouters;
    PyObject* pModule;
    PyObject* pClass;
    PyObject* pArgs;

    pModule = PyImport_ImportModule("qpid_dispatch_internal.router");
    QD_ERROR_PY_RET();
    pClass = PyObject_GetAttrString(pModule, "RouterEngine");
    Py_DECREF(pModule);
    QD_ERROR_PY_RET();

    PyObject *adapterType     = PyObject_GetAttrString(pDispatchModule, "RouterAdapter");
    QD_ERROR_PY_RET();
    PyObject *adapterInstance = PyObject_CallObject(adapterType, 0);
    QD_ERROR_PY_RET();

    ((RouterAdapter*) adapterInstance)->router = router;

    //
    // Constructor Arguments for RouterEngine
    //
    pArgs = PyTuple_New(4);

    // arg 0: adapter instance
    PyTuple_SetItem(pArgs, 0, adapterInstance);

    // arg 1: router_id
    pId = PyString_FromString(router->router_id);
    PyTuple_SetItem(pArgs, 1, pId);

    // arg 2: area_id
    pArea = PyString_FromString(router->router_area);
    PyTuple_SetItem(pArgs, 2, pArea);

    // arg 3: max_routers
    pMaxRouters = PyInt_FromLong((long) qd_bitmask_width());
    PyTuple_SetItem(pArgs, 3, pMaxRouters);

    //
    // Instantiate the router
    //
    pyRouter = PyInstance_New(pClass, pArgs, 0);
    Py_DECREF(pArgs);
    Py_DECREF(adapterType);
    QD_ERROR_PY_RET();

    pyTick = PyObject_GetAttrString(pyRouter, "handleTimerTick");
    QD_ERROR_PY_RET();
    pyAdded = PyObject_GetAttrString(pyRouter, "addressAdded");
    QD_ERROR_PY_RET();
    pyRemoved = PyObject_GetAttrString(pyRouter, "addressRemoved");
    QD_ERROR_PY_RET();
    pyLinkLost = PyObject_GetAttrString(pyRouter, "linkLost");
    QD_ERROR_PY_RET();
    return qd_error_code();
}