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; }
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; }
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; }
// 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; }
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); }
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); } }
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; }
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; }
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); }
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); }
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); } }
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; }
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(); }
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; }
// 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; }
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; }
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; }
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; }
/** * 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; }
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); }
/** * 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; }
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; }
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); } }
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); }
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); } }
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; }
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); }
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; }
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; }