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;
}
}