Changeset fac4f6c for router


Ignore:
Timestamp:
Mar 8, 2018 9:38:39 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
33b2d834
Parents:
69aadaa
Message:

Router: Check for transport compatibility before direct store of RI;
send through tunnel if incompatible
Fix repeated store of RI when IPv6-only
Move connect checker to own class for use by netdb
Log tweaks

Location:
router/java/src/net/i2p/router
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java

    r69aadaa rfac4f6c  
    3030import net.i2p.router.RouterContext;
    3131import net.i2p.router.TunnelInfo;
     32import net.i2p.router.tunnel.pool.ConnectChecker;
    3233import net.i2p.util.Log;
    3334import net.i2p.util.VersionComparator;
     
    4748    private final long _expiration;
    4849    private final PeerSelector _peerSelector;
     50    private final ConnectChecker _connectChecker;
     51    private final int _connectMask;
    4952
    5053    private final static int PARALLELIZATION = 4; // how many sent at a time
     
    7679        _expiration = context.clock().now() + timeoutMs;
    7780        _peerSelector = facade.getPeerSelector();
     81        if (data.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
     82            _connectChecker = null;
     83            _connectMask = 0;
     84        } else {
     85            _connectChecker = new ConnectChecker(context);
     86            RouterInfo us = context.router().getRouterInfo();
     87            if (us != null)
     88                _connectMask = _connectChecker.getOutboundMask(us);
     89            else
     90                _connectMask = ConnectChecker.ANY_V4;
     91        }
    7892    }
    7993
     
    334348        } else {
    335349            getContext().statManager().addRateData("netDb.storeRouterInfoSent", 1);
    336             sendDirect(msg, peer, expiration);
     350            // if we can't connect to peer directly, just send it out an exploratory tunnel
     351            if (_connectChecker.canConnect(_connectMask, peer))
     352                sendDirect(msg, peer, expiration);
     353            else
     354                sendStoreThroughGarlic(msg, peer, expiration);
    337355        }
    338356    }
     
    348366        msg.setReplyGateway(getContext().routerHash());
    349367
    350         if (_log.shouldLog(Log.DEBUG))
    351             _log.debug(getJobId() + ": send(dbStore) w/ token expected " + token);
    352        
    353368        _state.addPending(peer.getIdentity().getHash());
    354369       
     
    358373       
    359374        if (_log.shouldLog(Log.DEBUG))
    360             _log.debug("sending store directly to " + peer.getIdentity().getHash());
     375            _log.debug(getJobId() + ": sending store directly to " + peer.getIdentity().getHash());
    361376        OutNetMessage m = new OutNetMessage(getContext(), msg, expiration, STORE_PRIORITY, peer);
    362377        m.setOnFailedReplyJob(onFail);
     
    389404
    390405        if (_log.shouldLog(Log.DEBUG))
    391             _log.debug(getJobId() + ": send(dbStore) w/ token expected " + token);
     406            _log.debug(getJobId() + ": send store thru expl. tunnel to " + peer.getIdentity().getHash() + " w/ token expected " + token);
    392407       
    393408        _state.addPending(to);
     
    619634
    620635            if ( (_sendThrough != null) && (_msgSize > 0) ) {
    621                 if (_log.shouldLog(Log.INFO))
    622                     _log.info("sent a " + _msgSize + " byte netDb message through tunnel " + _sendThrough + " after " + howLong);
     636                if (_log.shouldDebug())
     637                    _log.debug("sent a " + _msgSize + " byte netDb message through tunnel " + _sendThrough + " after " + howLong);
    623638                for (int i = 0; i < _sendThrough.getLength(); i++)
    624639                    getContext().profileManager().tunnelDataPushed(_sendThrough.getPeer(i), howLong, _msgSize);
  • router/java/src/net/i2p/router/transport/udp/UDPTransport.java

    r69aadaa rfac4f6c  
    15821582        if (_needsRebuild) return true; // simple enough
    15831583        if (_context.router().isHidden()) return false;
    1584         RouterAddress addr = getCurrentAddress(false);
    1585         if (introducersRequired()) {
     1584        boolean v6Only = getIPv6Config() == IPV6_ONLY;
     1585        RouterAddress addr = getCurrentAddress(v6Only);
     1586        if (!v6Only && introducersRequired()) {
    15861587            UDPAddress ua = new UDPAddress(addr);
    15871588            long now = _context.clock().now();
     
    21402141        } else {
    21412142            if (!introducersRequired()) {
    2142                 RouterAddress cur = getCurrentExternalAddress(false);
     2143                boolean v6Only = getIPv6Config() == IPV6_ONLY;
     2144                RouterAddress cur = getCurrentExternalAddress(v6Only);
    21432145                if (cur != null)
    21442146                    host = cur.getHost();
  • router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java

    r69aadaa rfac4f6c  
    1313import java.util.StringTokenizer;
    1414
    15 import net.i2p.I2PAppContext;
    1615import net.i2p.crypto.SHA256Generator;
    1716import net.i2p.crypto.SigType;
     
    1918import net.i2p.data.DataHelper;
    2019import net.i2p.data.Hash;
    21 import net.i2p.data.router.RouterAddress;
    2220import net.i2p.data.router.RouterInfo;
    2321import net.i2p.router.Router;
    24 import net.i2p.router.CommSystemFacade.Status;
    2522import net.i2p.router.RouterContext;
    2623import net.i2p.router.TunnelPoolSettings;
    2724import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
    28 import net.i2p.router.transport.TransportManager;
    2925import net.i2p.router.transport.TransportUtil;
    3026import net.i2p.router.util.HashDistance;
     
    3632 * pool.
    3733 *
    38  * Todo: there's nothing non-static in here
    3934 */
    40 public abstract class TunnelPeerSelector {
    41     protected final RouterContext ctx;
    42     protected final Log log;
    43 
    44     private static final int NTCP_V4 = 0x01;
    45     private static final int SSU_V4 = 0x02;
    46     private static final int ANY_V4 = NTCP_V4 | SSU_V4;
    47     private static final int NTCP_V6 = 0x04;
    48     private static final int SSU_V6 = 0x08;
    49     private static final int ANY_V6 = NTCP_V6 | SSU_V6;
    50 
     35public abstract class TunnelPeerSelector extends ConnectChecker {
    5136
    5237    protected TunnelPeerSelector(RouterContext context) {
    53         ctx = context;
    54         log = ctx.logManager().getLog(getClass());
     38        super(context);
    5539    }
    5640
     
    121105            String peers = opts.getProperty("explicitPeers");
    122106            if (peers == null)
    123                 peers = I2PAppContext.getGlobalContext().getProperty("explicitPeers");
     107                peers = ctx.getProperty("explicitPeers");
    124108            if (peers != null)
    125109                return true;
     
    140124       
    141125        if (peers == null)
    142             peers = I2PAppContext.getGlobalContext().getProperty("explicitPeers");
     126            peers = ctx.getProperty("explicitPeers");
    143127       
    144128        List<Hash> rv = new ArrayList<Hash>();
     
    352336
    353337    /**
    354      *  Is NTCP disabled?
    355      *  @since 0.9.34
    356      */
    357     protected boolean isNTCPDisabled() {
    358         return !TransportManager.isNTCPEnabled(ctx);
    359     }
    360 
    361     /**
    362      *  Is SSU disabled?
    363      *  @since 0.9.34
    364      */
    365     protected boolean isSSUDisabled() {
    366         return !ctx.getBooleanPropertyDefaultTrue(TransportManager.PROP_ENABLE_UDP);
    367     }
    368 
    369     /**
    370338     *  Should we allow as OBEP?
    371339     *  This just checks for IPv4 support.
     
    760728        return rv;
    761729    }
    762 
    763     /**
    764      *  Can "from" connect to "to" based on published addresses?
    765      *
    766      *  This is intended for tunnel candidates, where we already have
    767      *  the RI. Will not force RI lookups.
    768      *  Either from or to may be us.
    769      *
    770      *  This is best effort, as we can't know for sure.
    771      *  Published addresses or introducers may have changed.
    772      *  Even if a can't connect to b, they may already be connected
    773      *  as b connected to a.
    774      *
    775      *  @return true if we don't have either RI
    776      *  @since 0.9.34
    777      */
    778     private boolean canConnect(Hash from, Hash to) {
    779         Hash us = ctx.routerHash();
    780         if (us == null)
    781             return true;
    782         boolean usf = from.equals(us);
    783         if (usf && ctx.commSystem().isEstablished(to))
    784             return true;
    785         boolean ust = to.equals(us);
    786         if (ust && ctx.commSystem().isEstablished(from))
    787             return true;
    788         RouterInfo rt = ctx.netDb().lookupRouterInfoLocally(to);
    789         if (rt == null)
    790             return true;
    791         RouterInfo rf = ctx.netDb().lookupRouterInfoLocally(from);
    792         if (rf == null)
    793             return true;
    794         int ct;
    795         if (ust) {
    796             // to us
    797             ct = getInboundMask(rt);
    798         } else {
    799             Collection<RouterAddress> at = rt.getAddresses();
    800             // assume nothing if hidden
    801             if (at.isEmpty())
    802                 return false;
    803             ct = getConnectMask(at);
    804         }
    805 
    806         int cf;
    807         if (usf) {
    808             // from us
    809             cf = getOutboundMask(rf);
    810         } else {
    811             Collection<RouterAddress> a = rf.getAddresses();
    812             if (a.isEmpty()) {
    813                 // assume IPv4 if hidden
    814                 cf = NTCP_V4 | SSU_V4;
    815             } else {
    816                 cf = getConnectMask(a);
    817             }
    818         }
    819 
    820         boolean rv = (ct & cf) != 0;
    821         if (!rv && log.shouldWarn()) {
    822             log.warn("Cannot connect: " +
    823                      (usf ? "us" : from.toString()) + " with mask " + cf + "\nto " +
    824                      (ust ? "us" : to.toString()) + " with mask " + ct);
    825         }
    826         return rv;
    827     }
    828 
    829     /**
    830      *  Can we connect to "to" based on published addresses?
    831      *
    832      *  This is intended for tunnel candidates, where we already have
    833      *  the RI. Will not force RI lookups.
    834      *
    835      *  This is best effort, as we can't know for sure.
    836      *  Does not check isEstablished(); do that first.
    837      *
    838      *  @since 0.9.34
    839      */
    840     private boolean canConnect(int ourMask, RouterInfo to) {
    841         Collection<RouterAddress> ra = to.getAddresses();
    842         // assume nothing if hidden
    843         if (ra.isEmpty())
    844             return false;
    845         int ct = getConnectMask(ra);
    846         boolean rv = (ourMask & ct) != 0;
    847         //if (!rv && log.shouldWarn())
    848         //    log.warn("Cannot connect: us with mask " + ourMask + " to " + to + " with mask " + ct);
    849         return rv;
    850     }
    851 
    852     /**
    853      *  Can "from" connect to us based on published addresses?
    854      *
    855      *  This is intended for tunnel candidates, where we already have
    856      *  the RI. Will not force RI lookups.
    857      *
    858      *  This is best effort, as we can't know for sure.
    859      *  Does not check isEstablished(); do that first.
    860      *
    861      *  @since 0.9.34
    862      */
    863     private boolean canConnect(RouterInfo from, int ourMask) {
    864         if (ourMask == 0)
    865             return false;
    866         Collection<RouterAddress> ra = from.getAddresses();
    867         int cf;
    868         // assume v4 if hidden
    869         if (ra.isEmpty())
    870             cf = NTCP_V4 | SSU_V4;
    871         else
    872             cf = getConnectMask(ra);
    873         boolean rv = (cf & ourMask) != 0;
    874         //if (!rv && log.shouldWarn())
    875         //    log.warn("Cannot connect: " + from + " with mask " + cf + " to us with mask " + ourMask);
    876         return rv;
    877     }
    878 
    879     /**
    880      *  Our inbound mask.
    881      *  For most cases, we use what we published, i.e. getConnectMask()
    882      *
    883      *  @return bitmask for accepting connections
    884      *  @since 0.9.34
    885      */
    886     private int getInboundMask(RouterInfo us) {
    887         // to us
    888         int ct = 0;
    889         Status status = ctx.commSystem().getStatus();
    890         switch (status) {
    891             case OK:
    892             case IPV4_UNKNOWN_IPV6_OK:
    893             case IPV4_FIREWALLED_IPV6_OK:
    894             case IPV4_SNAT_IPV6_OK:
    895             case IPV4_SNAT_IPV6_UNKNOWN:
    896             case IPV4_FIREWALLED_IPV6_UNKNOWN:
    897             case IPV4_UNKNOWN_IPV6_FIREWALLED:
    898             case IPV4_OK_IPV6_FIREWALLED:
    899             case DIFFERENT:
    900             case REJECT_UNSOLICITED:
    901                 // use what we published
    902                 Collection<RouterAddress> at = us.getAddresses();
    903                 if (at.isEmpty())
    904                     return 0;
    905                 ct = getConnectMask(at);
    906                 break;
    907 
    908             case IPV4_DISABLED_IPV6_OK:
    909             case IPV4_DISABLED_IPV6_UNKNOWN:
    910             // maybe should return zero for this one?
    911             case IPV4_DISABLED_IPV6_FIREWALLED:
    912                 // TODO look at force-firewalled settings per-transport
    913                 if (!isNTCPDisabled())
    914                     ct |= NTCP_V6;
    915                 if (!isSSUDisabled())
    916                     ct |= SSU_V6;
    917                 break;
    918 
    919             case IPV4_OK_IPV6_UNKNOWN:
    920             case DISCONNECTED:
    921             case HOSED:
    922             case UNKNOWN:
    923             default:
    924                 if (!isNTCPDisabled())
    925                     ct |= NTCP_V4;
    926                 if (!isSSUDisabled())
    927                     ct |= SSU_V4;
    928                 break;
    929         }
    930         return ct;
    931     }
    932 
    933     /**
    934      *  Our outbound mask.
    935      *  For most cases, we use our comm system status.
    936      *
    937      *  @return bitmask for initiating connections
    938      *  @since 0.9.34
    939      */
    940     private int getOutboundMask(RouterInfo us) {
    941         // from us
    942         int cf = 0;
    943         Status status = ctx.commSystem().getStatus();
    944         switch (status) {
    945             case OK:
    946                 // use what we published, as the OK state doesn't tell us about IPv6
    947                 // Addresses.isConnectedIPv6() is too slow
    948                 Collection<RouterAddress> a = us.getAddresses();
    949                 if (a.isEmpty()) {
    950                     // we are hidden
    951                     // TODO ipv6
    952                     if (!isNTCPDisabled())
    953                         cf |= NTCP_V4;
    954                     if (!isSSUDisabled())
    955                         cf |= SSU_V4;
    956                 } else {
    957                     cf = getConnectMask(a);
    958                 }
    959                 break;
    960 
    961             case IPV4_OK_IPV6_FIREWALLED:
    962             case IPV4_UNKNOWN_IPV6_OK:
    963             case IPV4_FIREWALLED_IPV6_OK:
    964             case IPV4_SNAT_IPV6_OK:
    965             case IPV4_UNKNOWN_IPV6_FIREWALLED:
    966                 if (!isNTCPDisabled())
    967                     cf |= NTCP_V4 | NTCP_V6;
    968                 if (!isSSUDisabled())
    969                     cf |= SSU_V4 | SSU_V6;
    970                 break;
    971 
    972             case IPV4_DISABLED_IPV6_OK:
    973             case IPV4_DISABLED_IPV6_UNKNOWN:
    974             case IPV4_DISABLED_IPV6_FIREWALLED:
    975                 if (!isNTCPDisabled())
    976                     cf |= NTCP_V6;
    977                 if (!isSSUDisabled())
    978                     cf |= SSU_V6;
    979                 break;
    980 
    981             case DIFFERENT:
    982             case IPV4_SNAT_IPV6_UNKNOWN:
    983             case IPV4_FIREWALLED_IPV6_UNKNOWN:
    984             case REJECT_UNSOLICITED:
    985             case IPV4_OK_IPV6_UNKNOWN:
    986             case DISCONNECTED:
    987             case HOSED:
    988             case UNKNOWN:
    989             default:
    990                 if (!isNTCPDisabled())
    991                     cf |= NTCP_V4;
    992                 if (!isSSUDisabled())
    993                     cf |= SSU_V4;
    994                 break;
    995         }
    996         return cf;
    997     }
    998 
    999     /** prevent object churn */
    1000     private static final String IHOST[] = { "ihost0", "ihost1", "ihost2" };
    1001 
    1002     /**
    1003      *  @param addrs non-empty, set your own default if empty
    1004      *  @return bitmask of v4/v6 NTCP/SSU
    1005      *  @since 0.9.34
    1006      */
    1007     private static int getConnectMask(Collection<RouterAddress> addrs) {
    1008         int rv = 0;
    1009         for (RouterAddress ra : addrs) {
    1010             String style = ra.getTransportStyle();
    1011             String host = ra.getHost();
    1012             if ("NTCP".equals(style)) {
    1013                 if (host != null) {
    1014                     if (host.contains(":"))
    1015                         rv |= NTCP_V6;
    1016                     else
    1017                         rv |= NTCP_V4;
    1018                 }
    1019             } else if ("SSU".equals(style)) {
    1020                 if (host == null) {
    1021                     for (int i = 0; i < 2; i++) {
    1022                         String ihost = ra.getOption(IHOST[i]);
    1023                         if (ihost == null)
    1024                             break;
    1025                         if (ihost.contains(":"))
    1026                             rv |= SSU_V6;
    1027                         else
    1028                             rv |= SSU_V4;
    1029                     }
    1030                 } else if (host.contains(":")) {
    1031                     rv |= SSU_V6;
    1032                 } else {
    1033                     rv |= SSU_V4;
    1034                 }
    1035             }
    1036         }
    1037         return rv;
    1038     }
    1039730}
Note: See TracChangeset for help on using the changeset viewer.