/** * Return a route error in case a route was found to be invalid as the current hop cannot find a * way to forward the message to the destination or any other hops in the forward part of the * route. In that case a negative route response is forwarded to the orginal source of the * message. Now of course we do not have any way to guarantee that the NACK message will be * received by the sender, but the best we can do is to try :-) * * <p>we send a query ID to NACKROUTE_QUERYID to indicate this is a bad Route * * @param src original source of the message * @param dest original destination of the message */ protected void generateNACKRoute(PeerID src, PeerID dest, Vector origHops) { // As long as the group is partially initialized, do not bother // trying to send NACKS. We can't: it just causes NPEs. if (resolver == null) { return; } if (LOG.isEnabledFor(Level.DEBUG)) { LOG.debug("generate NACK Route response " + src); } // check first, if we are not already in process of looking for a // route to the destination peer of the NACK. We should not try to // send a NACK to that destination at that point as this will block // our incoming processing thread while it is looking for a route to // that destination. If there a no pending route requests to that // destination then we can go ahead an attempt to send the NACK. At // the maximum we should have only one thread block while looking for // a specific destination. When we find a route to the destination, // the next NACK processing will be sent. if (router.isPendingRouteQuery(router.pid2addr(src))) { if (LOG.isEnabledFor(Level.DEBUG)) { LOG.debug("drop NACK due to pending route discovery " + src); } return; } // Generate a route response RouteAdvertisement route = (RouteAdvertisement) AdvertisementFactory.newAdvertisement(RouteAdvertisement.getAdvertisementType()); AccessPointAdvertisement ap = (AccessPointAdvertisement) AdvertisementFactory.newAdvertisement(AccessPointAdvertisement.getAdvertisementType()); ap.setPeerID(dest); route.setDest(ap); route.setHops(origHops); // set the the route of the peer that // detected the bad route RouteAdvertisement routeSrc = (RouteAdvertisement) AdvertisementFactory.newAdvertisement(RouteAdvertisement.getAdvertisementType()); AccessPointAdvertisement apSrc = (AccessPointAdvertisement) AdvertisementFactory.newAdvertisement(AccessPointAdvertisement.getAdvertisementType()); apSrc.setPeerID((PeerID) localPeerId); routeSrc.setDest(apSrc); RouteResponse routeResponse = new RouteResponse(); routeResponse.setDestRoute(route); routeResponse.setSrcRoute(routeSrc); if (routeResponse == null) { if (LOG.isEnabledFor(Level.DEBUG)) { LOG.debug("error creating route NACKresponse"); } return; } ResolverResponse res = new ResolverResponse( routerSName, credentialDoc, NACKROUTE_QUERYID, // mean NACKRoute routeResponse.toString()); // send the NACK response back to the originator resolver.sendResponse(src.toString(), res); }