static void qdr_link_inbound_second_attach_CT()

in src/router_core/connections.c [1902:2015]


static void qdr_link_inbound_second_attach_CT(qdr_core_t *core, qdr_action_t *action, bool discard)
{
    qdr_link_t       *link = safe_deref_qdr_link_t(action->args.connection.link);
    qdr_connection_t *conn = safe_deref_qdr_connection_t(action->args.connection.conn);
    qdr_terminus_t   *source = action->args.connection.source;
    qdr_terminus_t   *target = action->args.connection.target;

    if (discard || !link || !conn) {
        qdr_terminus_free(source);
        qdr_terminus_free(target);
        return;
    }

    link->oper_status = QDR_LINK_OPER_UP;
    link->attach_count++;

    //
    // Mark the link as an edge link if it's inside an edge connection.
    //
    link->edge = (conn->role == QDR_ROLE_EDGE_CONNECTION);

    if (link->core_endpoint) {
        qdrc_endpoint_do_second_attach_CT(core, link->core_endpoint, source, target);
        return;
    }

    //
    // Handle attach-routed links
    //
    if (link->connected_link) {
        qdr_terminus_t *remote_terminus = link->link_direction == QD_OUTGOING ? target : source;
        if (link->strip_prefix) {
            qdr_terminus_strip_address_prefix(remote_terminus, link->strip_prefix);
        }
        if (link->insert_prefix) {
            qdr_terminus_insert_address_prefix(remote_terminus, link->insert_prefix);
        }

        qdr_link_outbound_second_attach_CT(core, link->connected_link, source, target);
        return;
    }

    if (link->link_direction == QD_INCOMING) {
        //
        // Handle incoming link cases
        //
        switch (link->link_type) {
        case QD_LINK_ENDPOINT:
            if (link->auto_link) {
                //
                // This second-attach is the completion of an auto-link.  If the attach
                // has a valid source, transition the auto-link to the "active" state.
                //
                if (qdr_terminus_get_address(source)) {
                    link->auto_link->state = QDR_AUTO_LINK_STATE_ACTIVE;
                    qdr_core_bind_address_link_CT(core, link->auto_link->addr, link);
                }
            }

            //
            // Issue credit if this is an anonymous link or if its address has at least one reachable destination.
            //
            qdr_address_t *addr = link->owning_addr;
            if (!addr || (DEQ_SIZE(addr->subscriptions) || DEQ_SIZE(addr->rlinks) || qd_bitmask_cardinality(addr->rnodes)
                          || (!!addr->fallback && (DEQ_SIZE(addr->fallback->subscriptions)
                                                    || DEQ_SIZE(addr->fallback->rlinks)
                                                    || qd_bitmask_cardinality(addr->fallback->rnodes)))))
                qdr_link_issue_credit_CT(core, link, link->capacity, false);
            break;

        case QD_LINK_ROUTER:
            qdr_attach_link_data_CT(core, conn, link);
            // fall-through
        case QD_LINK_CONTROL:
            qdr_link_issue_credit_CT(core, link, link->capacity, false);
            break;

        case QD_LINK_EDGE_DOWNLINK:
            break;
        }
    } else {
        //
        // Handle outgoing link cases
        //
        switch (link->link_type) {
        case QD_LINK_ENDPOINT:
            if (link->auto_link) {
                //
                // This second-attach is the completion of an auto-link.  If the attach
                // has a valid target, transition the auto-link to the "active" state.
                //
                if (qdr_terminus_get_address(target)) {
                    link->auto_link->state = QDR_AUTO_LINK_STATE_ACTIVE;
                    qdr_core_bind_address_link_CT(core, link->auto_link->addr, link);
                }
            }
            break;

        case QD_LINK_CONTROL:
            qdr_attach_link_control_CT(core, conn, link);
            break;

        case QD_LINK_ROUTER:
            qdr_attach_link_data_CT(core, conn, link);
            break;

        case QD_LINK_EDGE_DOWNLINK:
            break;
        }
    }

    qdr_terminus_free(source);
    qdr_terminus_free(target);
}