/** Handle an FNPRoutedRejected message. */ private boolean handleRoutedRejected(Message m) { long id = m.getLong(DMT.UID); Long lid = Long.valueOf(id); RoutedContext rc = routedContexts.get(lid); if (rc == null) { // Gah Logger.error(this, "Unrecognized FNPRoutedRejected"); return false; // locally originated?? } short htl = rc.lastHtl; if (rc.source != null) htl = rc.source.decrementHTL(htl); short ohtl = m.getShort(DMT.HTL); if (ohtl < htl) htl = ohtl; if (htl == 0) { // Equivalent to DNF. // Relay. if (rc.source != null) { try { rc.source.sendAsync( DMT.createFNPRoutedRejected(id, (short) 0), null, nodeStats.routedMessageCtr); } catch (NotConnectedException e) { // Ouch. Logger.error(this, "Unable to relay probe DNF: peer disconnected: " + rc.source); } } } else { // Try routing to the next node forward(rc.msg, id, rc.source, htl, rc.msg.getDouble(DMT.TARGET_LOCATION), rc, rc.identity); } return true; }
/** * Handle a routed-to-a-specific-node message. * * @param m * @return False if we want the message put back on the queue. */ boolean handleRouted(Message m, PeerNode source) { if (logMINOR) Logger.minor(this, "handleRouted(" + m + ')'); long id = m.getLong(DMT.UID); Long lid = Long.valueOf(id); short htl = m.getShort(DMT.HTL); byte[] identity = ((ShortBuffer) m.getObject(DMT.NODE_IDENTITY)).getData(); if (source != null) htl = source.decrementHTL(htl); RoutedContext ctx; ctx = routedContexts.get(lid); if (ctx != null) { try { source.sendAsync(DMT.createFNPRoutedRejected(id, htl), null, nodeStats.routedMessageCtr); } catch (NotConnectedException e) { if (logMINOR) Logger.minor(this, "Lost connection rejecting " + m); } return true; } ctx = new RoutedContext(m, source, identity); synchronized (routedContexts) { routedContexts.put(lid, ctx); } // source == null => originated locally, keep full htl double target = m.getDouble(DMT.TARGET_LOCATION); if (logMINOR) Logger.minor(this, "id " + id + " from " + source + " htl " + htl + " target " + target); if (Math.abs(node.lm.getLocation() - target) <= Double.MIN_VALUE) { if (logMINOR) Logger.minor(this, "Dispatching " + m.getSpec() + " on " + node.getDarknetPortNumber()); // Handle locally // Message type specific processing dispatchRoutedMessage(m, source, id); return true; } else if (htl == 0) { Message reject = DMT.createFNPRoutedRejected(id, (short) 0); if (source != null) try { source.sendAsync(reject, null, nodeStats.routedMessageCtr); } catch (NotConnectedException e) { if (logMINOR) Logger.minor(this, "Lost connection rejecting " + m); } return true; } else { return forward(m, id, source, htl, target, ctx, identity); } }
private boolean forward( Message m, long id, PeerNode pn, short htl, double target, RoutedContext ctx, byte[] targetIdentity) { if (logMINOR) Logger.minor(this, "Should forward"); // Forward m = preForward(m, htl); while (true) { PeerNode next = node.peers.getByIdentity(targetIdentity); if (next != null && !next.isConnected()) { Logger.error(this, "Found target but disconnected!: " + next); next = null; } if (next == null) next = node.peers.closerPeer( pn, ctx.routedTo, target, true, node.isAdvancedModeEnabled(), -1, null, null, htl); if (logMINOR) Logger.minor(this, "Next: " + next + " message: " + m); if (next != null) { // next is connected, or at least has been => next.getPeer() CANNOT be null. if (logMINOR) Logger.minor(this, "Forwarding " + m.getSpec() + " to " + next.getPeer().getPort()); ctx.addSent(next); try { next.sendAsync(m, null, nodeStats.routedMessageCtr); } catch (NotConnectedException e) { continue; } } else { if (logMINOR) Logger.minor( this, "Reached dead end for " + m.getSpec() + " on " + node.getDarknetPortNumber()); // Reached a dead end... Message reject = DMT.createFNPRoutedRejected(id, htl); if (pn != null) try { pn.sendAsync(reject, null, nodeStats.routedMessageCtr); } catch (NotConnectedException e) { Logger.error(this, "Cannot send reject message back to source " + pn); return true; } } return true; } }