static void on_addr_event()

in src/router_core/modules/edge_addr_tracking/edge_addr_tracking.c [196:326]


static void on_addr_event(void *context, qdrc_event_t event, qdr_address_t *addr)
{
    // We only care about mobile addresses.
    if(!qdr_address_is_mobile_CT(addr))
        return;

    qdr_addr_tracking_module_context_t *addr_tracking = (qdr_addr_tracking_module_context_t*) context;
    switch (event) {
        case QDRC_EVENT_ADDR_BECAME_LOCAL_DEST : {
            //
            // This address transitioned from zero to one local destination. If this address already has more than zero remote destinations, don't do anything
            //
            if (qd_bitmask_cardinality(addr->rnodes) == 0) {
                qdr_link_ref_t *inlink = DEQ_HEAD(addr->inlinks);
                //
                // Every inlink that has an edge context must be informed of the appearence of this address.
                //
                while (inlink) {
                    if(inlink->link->edge_context != 0) {
                        qdr_addr_endpoint_state_t *endpoint_state = (qdr_addr_endpoint_state_t *)inlink->link->edge_context;
                        if (!endpoint_state->closed && qdrc_can_send_address(addr, endpoint_state->conn) ) {
                            qdrc_endpoint_t *endpoint = endpoint_state->endpoint;
                            qdrc_send_message(addr_tracking->core, addr, endpoint, true);
                        }
                    }
                    inlink = DEQ_NEXT(inlink);
                }
            }
            break;
        }
        case QDRC_EVENT_ADDR_BECAME_DEST : {
            //
            // This address transitioned from zero to one destination. If this address already had local destinations
            //
            qdr_link_ref_t *inlink = DEQ_HEAD(addr->inlinks);
            //
            // Every inlink that has an edge context must be informed of the appearence of this address.
            //
            while (inlink) {
                if(inlink->link->edge_context != 0) {
                    qdr_addr_endpoint_state_t *endpoint_state = (qdr_addr_endpoint_state_t *)inlink->link->edge_context;
                    if (!endpoint_state->closed && qdrc_can_send_address(addr, endpoint_state->conn) ) {
                        qdrc_endpoint_t *endpoint = endpoint_state->endpoint;
                        if (endpoint)
                            qdrc_send_message(addr_tracking->core, addr, endpoint, true);
                    }
                }
                inlink = DEQ_NEXT(inlink);
            }
        }
        break;

        case QDRC_EVENT_ADDR_NO_LONGER_DEST :

            // fallthrough

        case QDRC_EVENT_ADDR_NO_LONGER_LOCAL_DEST : {
            // The address no longer has any local destinations.
            // If there are no remote destinations either, we have to tell the edge routers to delete their sender links
            if (qd_bitmask_cardinality(addr->rnodes) == 0) {
                qdr_link_ref_t *inlink = DEQ_HEAD(addr->inlinks);
                //
                // Every inlink that has an edge context must be informed of the disappearence of this address.
                //
                while (inlink) {
                    if(inlink->link->edge_context != 0) {
                        qdr_addr_endpoint_state_t *endpoint_state = (qdr_addr_endpoint_state_t *)inlink->link->edge_context;
                        if(!endpoint_state->closed) {
                            qdrc_endpoint_t *endpoint = endpoint_state->endpoint;
                            if (endpoint)
                                qdrc_send_message(addr_tracking->core, addr, endpoint, false);
                        }
                    }
                    inlink = DEQ_NEXT(inlink);
                }
            }

            break;
        }
        case QDRC_EVENT_ADDR_ONE_LOCAL_DEST: {
            //
            // This address transitioned from N destinations to one local dest
            // If this address already has non-zero remote destinations, there is no need to tell the edge routers about it
            //
            assert(DEQ_SIZE(addr->rlinks) == 1);
            //
            // There should be only one rlink in the rlinks list
            //
            qdr_link_ref_t *rlink_ref = DEQ_HEAD(addr->rlinks);
            qdr_link_t *link = rlink_ref->link;

            qdr_link_ref_t *inlink = DEQ_HEAD(addr->inlinks);
            while (inlink) {
                if (inlink->link->edge_context != 0) {
                    qdr_addr_endpoint_state_t *endpoint_state = (qdr_addr_endpoint_state_t *)inlink->link->edge_context;
                    qdrc_endpoint_t *endpoint = endpoint_state->endpoint;
                    if (endpoint_state->conn == link->conn && !endpoint_state->closed) {
                        qdrc_send_message(addr_tracking->core, addr, endpoint, false);
                        break;
                    }
                }
                inlink = DEQ_NEXT(inlink);
            }
        }
        break;
        case QDRC_EVENT_ADDR_TWO_DEST: {
            //
            // The address transitioned from one local dest to two destinations, The second destination might be local or remote.
            //
            qdr_link_ref_t *rlink_ref = DEQ_HEAD(addr->rlinks);
            qdr_link_t *link = rlink_ref->link;

            qdr_link_ref_t *inlink = DEQ_HEAD(addr->inlinks);
            while (inlink) {
                if(inlink->link->edge_context != 0) {
                    qdr_addr_endpoint_state_t *endpoint_state = (qdr_addr_endpoint_state_t *)inlink->link->edge_context;
                    qdrc_endpoint_t *endpoint = endpoint_state->endpoint;
                    if (link->conn == endpoint_state->conn && !endpoint_state->closed) {
                        qdrc_send_message(addr_tracking->core, addr, endpoint, true);
                        break;
                    }
                }
                inlink = DEQ_NEXT(inlink);
            }
            break;
        }

        default:
            break;
    }
}