Ejemplo n.º 1
0
void qd_connection_manager_start(qd_dispatch_t *qd)
{
    static bool first_start = true;
    qd_listener_t  *li = DEQ_HEAD(qd->connection_manager->listeners);
    qd_connector_t *ct = DEQ_HEAD(qd->connection_manager->connectors);

    while (li) {
        if (!li->pn_listener) {
            if (!qd_listener_listen(li) && first_start) {
                qd_log(qd->connection_manager->log_source, QD_LOG_CRITICAL,
                       "Listen on %s failed during initial config", li->config.host_port);
                exit(1);
            } else {
                li->exit_on_error = first_start;
            }
        }
        li = DEQ_NEXT(li);
    }

    while (ct) {
        qd_connector_connect(ct);
        ct = DEQ_NEXT(ct);
    }

    first_start = false;
}
Ejemplo n.º 2
0
static char* list_well_formed(item_list_t list, char *key)
{
    item_t *ptr;
    item_t *last  = 0;
    int     size  = DEQ_SIZE(list);
    int     count = 0;
    char    str[32];

    ptr = DEQ_HEAD(list);
    while (ptr) {
        str[count] = ptr->letter;
        count++;
        if (DEQ_PREV(ptr) != last) return "Corrupt previous link";
        last = ptr;
        ptr = DEQ_NEXT(ptr);
    }
    str[count] = '\0';
    if (strcmp(str, key) != 0) return "Invalid key";

    if (count != size) return "Size different from number of items (forward)";

    count = 0;
    last  = 0;
    ptr   = DEQ_TAIL(list);
    while (ptr) {
        count++;
        if (DEQ_NEXT(ptr) != last) return "Corrupt next link";
        last = ptr;
        ptr = DEQ_PREV(ptr);
    }

    if (count != size) return "Size different from number of items (backward)";

    return 0;
}
Ejemplo n.º 3
0
static int get_failover_info_length(qd_failover_item_list_t   conn_info_list)
{
    int arr_length = 0;
    qd_failover_item_t *item = DEQ_HEAD(conn_info_list);

    item = DEQ_NEXT(item);
    while(item) {
        if (item->scheme) {
            // The +3 is for the '://'
            arr_length += strlen(item->scheme) + 3;
        }
        if (item->host_port) {
            arr_length += strlen(item->host_port);
        }
        item = DEQ_NEXT(item);
        if (item) {
            // This is for the comma between the items
            arr_length += 2;
        }
    }

    if (arr_length > 0)
        // This is for the final '\0'
        arr_length += 1;

    return arr_length;
}
Ejemplo n.º 4
0
// get the link route by either name or id
static qdr_link_route_t *_find_link_route_CT(qdr_connection_t *conn,
                                             qd_iterator_t *name, qd_iterator_t *identity)
{
    qdr_link_route_t *lr = NULL;

    // if both id and name provided, prefer id
    //
    if (identity) {
        char buf[64];
        uint64_t id = 0;
        assert(qd_iterator_length(identity) < sizeof(buf));
        qd_iterator_strncpy(identity, buf, sizeof(buf));
        if (sscanf(buf, "%"SCNu64, &id) != 1) {
            return NULL;
        }
        lr = DEQ_HEAD(conn->conn_link_routes);
        while (lr) {
            if (id == lr->identity)
                break;
            lr = DEQ_NEXT(lr);
        }
    } else if (name) {
        lr = DEQ_HEAD(conn->conn_link_routes);
        while (lr) {
            if (qd_iterator_equal(name, (unsigned char *)lr->name))
                break;
            lr = DEQ_NEXT(lr);
        }
    }

    return lr;
}
Ejemplo n.º 5
0
void qdra_link_get_next_CT(qdr_core_t *core, qdr_query_t *query)
{
    qdr_link_t *link = 0;

        if (query->next_offset < DEQ_SIZE(core->open_links)) {
            link = DEQ_HEAD(core->open_links);
            for (int i = 0; i < query->next_offset && link; i++)
                link = DEQ_NEXT(link);
        }

    if (link) {
        //
        // Write the columns of the link entity into the response body.
        //
        qdr_agent_write_link_CT(query, link);

        //
        // Advance to the next link
        //
        qdr_manage_advance_link_CT(query, link);
    } else
        query->more = false;

    //
    // Enqueue the response.
    //
    qdr_agent_enqueue_response_CT(core, query);
}
Ejemplo n.º 6
0
static void notify_opened(qd_container_t *container, qd_connection_t *conn, void *context)
{
    const qd_node_type_t *nt;

    //
    // Note the locking structure in this function.  Generally this would be unsafe, but since
    // this particular list is only ever appended to and never has items inserted or deleted,
    // this usage is safe in this case.
    //
    sys_mutex_lock(container->lock);
    qdc_node_type_t *nt_item = DEQ_HEAD(container->node_type_list);
    sys_mutex_unlock(container->lock);

    while (nt_item) {
        nt = nt_item->ntype;
        if (qd_connection_inbound(conn)) {
            if (nt->inbound_conn_opened_handler)
                nt->inbound_conn_opened_handler(nt->type_context, conn, context);
        } else {
            if (nt->outbound_conn_opened_handler)
                nt->outbound_conn_opened_handler(nt->type_context, conn, context);
        }

        sys_mutex_lock(container->lock);
        nt_item = DEQ_NEXT(nt_item);
        sys_mutex_unlock(container->lock);
    }
}
Ejemplo n.º 7
0
unsigned int qd_buffer_list_clone(qd_buffer_list_t *dst, const qd_buffer_list_t *src)
{
    uint32_t len = 0;
    DEQ_INIT(*dst);
    qd_buffer_t *buf = DEQ_HEAD(*src);
    while (buf) {
        size_t to_copy = qd_buffer_size(buf);
        unsigned char *src = qd_buffer_base(buf);
        len += to_copy;
        while (to_copy) {
            qd_buffer_t *newbuf = qd_buffer();
            size_t count = qd_buffer_capacity(newbuf);
            // default buffer capacity may have changed,
            // so don't assume it will fit:
            if (count > to_copy) count = to_copy;
            memcpy(qd_buffer_cursor(newbuf), src, count);
            qd_buffer_insert(newbuf, count);
            DEQ_INSERT_TAIL(*dst, newbuf);
            src += count;
            to_copy -= count;
        }
        buf = DEQ_NEXT(buf);
    }
    return len;
}
Ejemplo n.º 8
0
static int writable_handler(qd_container_t *container, pn_connection_t *conn, qd_connection_t* qd_conn)
{
    const qd_node_type_t *nt;
    int                   event_count = 0;

    //
    // Note the locking structure in this function.  Generally this would be unsafe, but since
    // this particular list is only ever appended to and never has items inserted or deleted,
    // this usage is safe in this case.
    //
    sys_mutex_lock(container->lock);
    qdc_node_type_t *nt_item = DEQ_HEAD(container->node_type_list);
    sys_mutex_unlock(container->lock);

    while (nt_item) {
        nt = nt_item->ntype;
        if (nt->writable_handler)
            event_count += nt->writable_handler(nt->type_context, qd_conn, 0);

        sys_mutex_lock(container->lock);
        nt_item = DEQ_NEXT(nt_item);
        sys_mutex_unlock(container->lock);
    }

    return event_count;
}
Ejemplo n.º 9
0
void qdra_config_auto_link_get_next_CT(qdr_core_t *core, qdr_query_t *query)
{
    qdr_auto_link_t *al = 0;

    if (query->next_offset < DEQ_SIZE(core->auto_links)) {
        al = DEQ_HEAD(core->auto_links);
        for (int i = 0; i < query->next_offset && al; i++)
            al = DEQ_NEXT(al);
    }

    if (al) {
        //
        // Write the columns of the addr entity into the response body.
        //
        qdr_agent_write_config_auto_link_CT(query, al);

        //
        // Advance to the next object
        //
        qdr_manage_advance_config_auto_link_CT(query, al);
    } else
        query->more = false;

    //
    // Enqueue the response.
    //
    qdr_agent_enqueue_response_CT(core, query);
}
void qdra_config_link_route_get_next_CT(qdr_core_t *core, qdr_query_t *query)
{
    qdr_link_route_t *lr = 0;

    if (query->next_offset < DEQ_SIZE(core->link_routes)) {
        lr = DEQ_HEAD(core->link_routes);
        for (int i = 0; i < query->next_offset && lr; i++)
            lr = DEQ_NEXT(lr);
    }

    if (lr) {
        //
        // Write the columns of the addr entity into the response body.
        //
        qdr_agent_write_config_link_route_CT(query, lr);

        //
        // Advance to the next object
        //
        qdr_manage_advance_config_link_route_CT(query, lr);
    } else
        query->more = false;

    //
    // Enqueue the response.
    //
    qdr_agent_enqueue_response_CT(core, query);
}
Ejemplo n.º 11
0
void qdr_route_del_auto_link_CT(qdr_core_t *core, qdr_auto_link_t *al)
{
    //
    // Disassociate from the connection identifier.  Check to see if the identifier
    // should be removed.
    //
    qdr_conn_identifier_t *cid = al->conn_id;
    if (cid) {
        qdr_connection_ref_t * cref = DEQ_HEAD(cid->connection_refs);
        while (cref) {
            qdr_auto_link_deactivate_CT(core, al, cref->conn);
            cref = DEQ_NEXT(cref);
        }
        DEQ_REMOVE_N(REF, cid->auto_link_refs, al);
        qdr_route_check_id_for_deletion_CT(core, cid);
    }

    //
    // Disassociate the auto link from its address.  Check to see if the address
    // should be removed.
    //
    qdr_address_t *addr = al->addr;
    if (addr && --addr->ref_count == 0)
        qdr_check_addr_CT(core, addr, false);

    //
    // Remove the auto link from the core list.
    //
    DEQ_REMOVE(core->auto_links, al);
    free(al->name);
    free(al->external_addr);
    free_qdr_auto_link_t(al);
}
Ejemplo n.º 12
0
void qd_connection_manager_start(qd_dispatch_t *qd)
{
    qd_config_listener_t  *cl = DEQ_HEAD(qd->connection_manager->config_listeners);
    qd_config_connector_t *cc = DEQ_HEAD(qd->connection_manager->config_connectors);

    while (cl) {
        if (cl->listener == 0)
            cl->listener = qd_server_listen(qd, &cl->configuration, cl);
        cl = DEQ_NEXT(cl);
    }

    while (cc) {
        if (cc->connector == 0)
            cc->connector = qd_server_connect(qd, &cc->configuration, cc);
        cc = DEQ_NEXT(cc);
    }
}
Ejemplo n.º 13
0
qdr_auto_link_t *qdr_route_add_auto_link_CT(qdr_core_t          *core,
                                            qd_iterator_t       *name,
                                            qd_parsed_field_t   *addr_field,
                                            qd_direction_t       dir,
                                            int                  phase,
                                            qd_parsed_field_t   *container_field,
                                            qd_parsed_field_t   *connection_field,
                                            qd_parsed_field_t   *external_addr)
{
    qdr_auto_link_t *al = new_qdr_auto_link_t();

    //
    // Set up the auto_link structure
    //
    ZERO(al);
    al->identity      = qdr_identifier(core);
    al->name          = name ? (char*) qd_iterator_copy(name) : 0;
    al->dir           = dir;
    al->phase         = phase;
    al->state         = QDR_AUTO_LINK_STATE_INACTIVE;
    al->external_addr = external_addr ? (char*) qd_iterator_copy(qd_parse_raw(external_addr)) : 0;

    //
    // Find or create an address for the auto_link destination
    //
    qd_iterator_t *iter = qd_parse_raw(addr_field);
    qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH);
    qd_iterator_annotate_phase(iter, (char) phase + '0');

    qd_hash_retrieve(core->addr_hash, iter, (void*) &al->addr);
    if (!al->addr) {
        al->addr = qdr_address_CT(core, qdr_treatment_for_address_CT(core, 0, iter, 0, 0));
        DEQ_INSERT_TAIL(core->addrs, al->addr);
        qd_hash_insert(core->addr_hash, iter, al->addr, &al->addr->hash_handle);
    }

    al->addr->ref_count++;

    //
    // Find or create a connection identifier structure for this auto_link
    //
    if (container_field || connection_field) {
        al->conn_id = qdr_route_declare_id_CT(core, qd_parse_raw(container_field), qd_parse_raw(connection_field));
        DEQ_INSERT_TAIL_N(REF, al->conn_id->auto_link_refs, al);
        qdr_connection_ref_t * cref = DEQ_HEAD(al->conn_id->connection_refs);
        while (cref) {
            qdr_auto_link_activate_CT(core, al, cref->conn);
            cref = DEQ_NEXT(cref);
        }
    }

    //
    // Add the auto_link to the core list
    //
    DEQ_INSERT_TAIL(core->auto_links, al);

    return al;
}
Ejemplo n.º 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();
}
Ejemplo n.º 15
0
static void qdr_manage_advance_address_CT(qdr_query_t *query, qdr_address_t *addr)
{
    query->next_offset++;
    addr = DEQ_NEXT(addr);
    if (addr) {
        query->more     = true;
        query->next_key = qdr_field((const char*) qd_hash_key_by_handle(addr->hash_handle));
    } else
        query->more = false;
}
Ejemplo n.º 16
0
// get conn via identity
static qdr_connection_t *_find_conn_CT(qdr_core_t *core, uint64_t conn_id)
{
    qdr_connection_t *conn = DEQ_HEAD(core->open_connections);
    while (conn) {
        if (conn->identity == conn_id)
            break;
        conn = DEQ_NEXT(conn);
    }
    return conn;
}
Ejemplo n.º 17
0
unsigned int qd_buffer_list_length(const qd_buffer_list_t *list)
{
    unsigned int len = 0;
    qd_buffer_t *buf = DEQ_HEAD(*list);
    while (buf) {
        len += qd_buffer_size(buf);
        buf = DEQ_NEXT(buf);
    }
    return len;
}
Ejemplo n.º 18
0
static void qdr_manage_advance_link_CT(qdr_query_t *query, qdr_link_t *link)
{
    query->next_offset++;
    link = DEQ_NEXT(link);
    if (link) {
        query->more     = true;
        //query->next_key = qdr_field((const char*) qd_hash_key_by_handle(link->owning_addr->hash_handle));
    } else
        query->more = false;
}
Ejemplo n.º 19
0
qdr_link_route_t *qdr_route_add_link_route_CT(qdr_core_t             *core,
                                              qd_iterator_t          *name,
                                              qd_parsed_field_t      *prefix_field,
                                              qd_parsed_field_t      *container_field,
                                              qd_parsed_field_t      *connection_field,
                                              qd_address_treatment_t  treatment,
                                              qd_direction_t          dir)
{
    qdr_link_route_t *lr = new_qdr_link_route_t();

    //
    // Set up the link_route structure
    //
    ZERO(lr);
    lr->identity  = qdr_identifier(core);
    lr->name      = name ? (char*) qd_iterator_copy(name) : 0;
    lr->dir       = dir;
    lr->treatment = treatment;

    //
    // Find or create an address for link-attach routing
    //
    qd_iterator_t *iter = qd_parse_raw(prefix_field);
    qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH);
    qd_iterator_annotate_prefix(iter, dir == QD_INCOMING ? 'C' : 'D');

    qd_hash_retrieve(core->addr_hash, iter, (void*) &lr->addr);
    if (!lr->addr) {
        lr->addr = qdr_address_CT(core, treatment);
        DEQ_INSERT_TAIL(core->addrs, lr->addr);
        qd_hash_insert(core->addr_hash, iter, lr->addr, &lr->addr->hash_handle);
    }

    lr->addr->ref_count++;

    //
    // Find or create a connection identifier structure for this link route
    //
    if (container_field || connection_field) {
        lr->conn_id = qdr_route_declare_id_CT(core, qd_parse_raw(container_field), qd_parse_raw(connection_field));
        DEQ_INSERT_TAIL_N(REF, lr->conn_id->link_route_refs, lr);
        qdr_connection_ref_t * cref = DEQ_HEAD(lr->conn_id->connection_refs);
        while (cref) {
            qdr_link_route_activate_CT(core, lr, cref->conn);
            cref = DEQ_NEXT(cref);
        }
    }

    //
    // Add the link route to the core list
    //
    DEQ_INSERT_TAIL(core->link_routes, lr);

    return lr;
}
Ejemplo n.º 20
0
/**
 * Search the list of config_ssl_profiles for an ssl-profile that matches the passed in name
 */
static qd_config_ssl_profile_t *qd_find_ssl_profile(qd_connection_manager_t *cm, char *name)
{
    qd_config_ssl_profile_t *ssl_profile = DEQ_HEAD(cm->config_ssl_profiles);
    while (ssl_profile) {
        if (strcmp(ssl_profile->name, name) == 0)
            return ssl_profile;
        ssl_profile = DEQ_NEXT(ssl_profile);
    }

    return 0;
}
Ejemplo n.º 21
0
static void qdr_del_router_CT(qdr_core_t *core, qdr_action_t *action, bool discard)
{
    int router_maskbit = action->args.route_table.router_maskbit;

    if (router_maskbit >= qd_bitmask_width() || router_maskbit < 0) {
        qd_log(core->log, QD_LOG_CRITICAL, "del_router: Router maskbit out of range: %d", router_maskbit);
        return;
    }

    if (core->routers_by_mask_bit[router_maskbit] == 0) {
        qd_log(core->log, QD_LOG_CRITICAL, "del_router: Deleting nonexistent router: %d", router_maskbit);
        return;
    }

    qdr_node_t    *rnode = core->routers_by_mask_bit[router_maskbit];
    qdr_address_t *oaddr = rnode->owning_addr;
    assert(oaddr);

    //
    // Unlink the router node from the address record
    //
    qd_bitmask_clear_bit(oaddr->rnodes, router_maskbit);
    qd_bitmask_clear_bit(core->router_addr_T->rnodes, router_maskbit);
    qd_bitmask_clear_bit(core->routerma_addr_T->rnodes, router_maskbit);
    rnode->ref_count -= 3;

    //
    // While the router node has a non-zero reference count, look for addresses
    // to unlink the node from.
    //
    qdr_address_t *addr = DEQ_HEAD(core->addrs);
    while (addr && rnode->ref_count > 0) {
        if (qd_bitmask_clear_bit(addr->rnodes, router_maskbit))
            //
            // If the cleared bit was originally set, decrement the ref count
            //
            rnode->ref_count--;
        addr = DEQ_NEXT(addr);
    }
    assert(rnode->ref_count == 0);

    //
    // Free the router node and the owning address records.
    //
    qd_bitmask_free(rnode->valid_origins);
    DEQ_REMOVE(core->routers, rnode);
    free_qdr_node_t(rnode);

    qd_hash_remove_by_handle(core->addr_hash, oaddr->hash_handle);
    DEQ_REMOVE(core->addrs, oaddr);
    qd_hash_handle_free(oaddr->hash_handle);
    core->routers_by_mask_bit[router_maskbit] = 0;
    free_qdr_address_t(oaddr);
}
Ejemplo n.º 22
0
/**
 * Search the list of config_sasl_plugins for an sasl-profile that matches the passed in name
 */
static qd_config_sasl_plugin_t *qd_find_sasl_plugin(qd_connection_manager_t *cm, char *name)
{
    qd_config_sasl_plugin_t *sasl_plugin = DEQ_HEAD(cm->config_sasl_plugins);
    while (sasl_plugin) {
        if (strcmp(sasl_plugin->name, name) == 0)
            return sasl_plugin;
        sasl_plugin = DEQ_NEXT(sasl_plugin);
    }

    return 0;
}
Ejemplo n.º 23
0
qd_config_connector_t *qd_connection_manager_find_on_demand(qd_dispatch_t *qd, const char *name)
{
    qd_config_connector_t *cc = DEQ_HEAD(qd->connection_manager->on_demand_connectors);

    while (cc) {
        if (strcmp(cc->configuration.name, name) == 0)
            break;
        cc = DEQ_NEXT(cc);
    }

    return cc;
}
Ejemplo n.º 24
0
void qdr_del_connection_ref(qdr_connection_ref_list_t *ref_list, qdr_connection_t *conn)
{
    qdr_connection_ref_t *ref = DEQ_HEAD(*ref_list);
    while (ref) {
        if (ref->conn == conn) {
            DEQ_REMOVE(*ref_list, ref);
            free_qdr_connection_ref_t(ref);
            break;
        }
        ref = DEQ_NEXT(ref);
    }
}
Ejemplo n.º 25
0
void qdra_conn_link_route_get_first_CT(qdr_core_t *core, qdr_query_t *query, int offset)
{
    query->status = QD_AMQP_OK;

    qdr_connection_t *conn = _find_conn_CT(core, query->in_conn);
    if (!conn || offset >= DEQ_SIZE(conn->conn_link_routes)) {
        query->more = false;
    } else {
        // Find the lr at the offset.
        //
        qdr_link_route_t *lr = DEQ_HEAD(conn->conn_link_routes);
        for (int i = 0; i < offset && lr; i++)
            lr = DEQ_NEXT(lr);
        assert(lr);
        // write the lr into the response and advance to next
        _write_as_list_CT(query, lr);
        query->next_offset = offset + 1;
        query->more = DEQ_NEXT(lr) != NULL;
    }
    qdr_agent_enqueue_response_CT(core, query);
}
Ejemplo n.º 26
0
void qdr_del_node_ref(qdr_router_ref_list_t *ref_list, qdr_node_t *rnode)
{
    qdr_router_ref_t *ref = DEQ_HEAD(*ref_list);
    while (ref) {
        if (ref->router == rnode) {
            DEQ_REMOVE(*ref_list, ref);
            free_qdr_router_ref_t(ref);
            rnode->ref_count--;
            break;
        }
        ref = DEQ_NEXT(ref);
    }
}
Ejemplo n.º 27
0
qd_parsed_field_t *qd_parse_sub_value(qd_parsed_field_t *field, uint32_t idx)
{
    if (field->tag == QD_AMQP_MAP8 || field->tag == QD_AMQP_MAP32)
        idx = (idx << 1) + 1;

    qd_parsed_field_t *key = DEQ_HEAD(field->children);
    while (idx && key) {
        idx--;
        key = DEQ_NEXT(key);
    }

    return key;
}
Ejemplo n.º 28
0
void qdra_conn_link_route_get_next_CT(qdr_core_t *core, qdr_query_t *query)
{
    qdr_connection_t *conn = _find_conn_CT(core, query->in_conn);
    if (!conn || query->next_offset >= DEQ_SIZE(conn->conn_link_routes)) {
        query->more = false;
    } else {
        // find the lr at the offset
        //
        qdr_link_route_t *lr = DEQ_HEAD(conn->conn_link_routes);
        for (int i = 0; i < query->next_offset && lr; i++)
            lr = DEQ_NEXT(lr);

        if (lr) {
            // write response and advance to next
            _write_as_list_CT(query, lr);
            ++query->next_offset;
            query->more = DEQ_NEXT(lr) != NULL;
        } else
            query->more = false;
    }
    qdr_agent_enqueue_response_CT(core, query);
}
Ejemplo n.º 29
0
qd_parsed_field_t *qd_parse_sub_key(qd_parsed_field_t *field, uint32_t idx)
{
    if (field->tag != QD_AMQP_MAP8 && field->tag != QD_AMQP_MAP32)
        return 0;

    idx = idx << 1;
    qd_parsed_field_t *key = DEQ_HEAD(field->children);
    while (idx && key) {
        idx--;
        key = DEQ_NEXT(key);
    }

    return key;
}
Ejemplo n.º 30
0
static qdr_auto_link_t *qdr_auto_link_config_find_by_name_CT(qdr_core_t *core, qd_field_iterator_t *name)
{
    if (!name)
        return 0;

    qdr_auto_link_t *rc = DEQ_HEAD(core->auto_links);
    while (rc) { // Sometimes the name can be null
        if (rc->name && qd_field_iterator_equal(name, (const unsigned char*) rc->name))
            break;
        rc = DEQ_NEXT(rc);
    }

    return rc;
}