Search in sources :

Example 21 with RouterAddress

use of net.i2p.data.router.RouterAddress in project i2p.i2p by i2p.

the class UDPTransport method bid.

public TransportBid bid(RouterInfo toAddress, long dataSize) {
    if (dataSize > OutboundMessageState.MAX_MSG_SIZE) {
        // NTCP max is lower, so msg will get dropped
        return null;
    }
    Hash to = toAddress.getIdentity().calculateHash();
    PeerState peer = getPeerState(to);
    if (peer != null) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("bidding on a message to an established peer: " + peer);
        if (preferUDP())
            return _cachedBid[FAST_PREFERRED_BID];
        else
            return _cachedBid[FAST_BID];
    } else {
        // If we don't have a port, all is lost
        if (_reachabilityStatus == Status.HOSED) {
            markUnreachable(to);
            return null;
        }
        // Validate his SSU address
        RouterAddress addr = getTargetAddress(toAddress);
        if (addr == null) {
            markUnreachable(to);
            return null;
        }
        // Check for supported sig type
        SigType type = toAddress.getIdentity().getSigType();
        if (type == null || !type.isAvailable()) {
            markUnreachable(to);
            return null;
        }
        // Can we connect to them if we are not DSA?
        RouterInfo us = _context.router().getRouterInfo();
        if (us != null) {
            RouterIdentity id = us.getIdentity();
            if (id.getSigType() != SigType.DSA_SHA1) {
                String v = toAddress.getVersion();
                if (VersionComparator.comp(v, MIN_SIGTYPE_VERSION) < 0) {
                    markUnreachable(to);
                    return null;
                }
            }
        }
        if (!allowConnection())
            return _cachedBid[TRANSIENT_FAIL_BID];
        if (_log.shouldLog(Log.DEBUG))
            _log.debug("bidding on a message to an unestablished peer: " + to);
        // Try to maintain at least 5 peers (30 for v6) so we can determine our IP address and
        // we have a selection to run peer tests with.
        // If we are firewalled, and we don't have enough peers that volunteered to
        // also introduce us, also bid aggressively so we are preferred over NTCP.
        // (Otherwise we only talk UDP to those that are firewalled, and we will
        // never get any introducers)
        int count = _peersByIdent.size();
        if (alwaysPreferUDP()) {
            return _cachedBid[SLOW_PREFERRED_BID];
        } else if (count < _min_peers || (_haveIPv6Address && count < _min_v6_peers) || (introducersRequired() && _introManager.introducerCount() < MIN_INTRODUCER_POOL)) {
            // TODO After some time, decide that UDP is blocked/broken and return TRANSIENT_FAIL_BID?
            if (_context.random().nextInt(4) == 0)
                return _cachedBid[SLOWEST_BID];
            else
                return _cachedBid[SLOW_PREFERRED_BID];
        } else if (preferUDP()) {
            return _cachedBid[SLOW_BID];
        } else if (haveCapacity()) {
            if (addr.getCost() > DEFAULT_COST)
                return _cachedBid[SLOWEST_COST_BID];
            else
                return _cachedBid[SLOWEST_BID];
        } else {
            if (addr.getCost() > DEFAULT_COST)
                return _cachedBid[NEAR_CAPACITY_COST_BID];
            else
                return _cachedBid[NEAR_CAPACITY_BID];
        }
    }
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) RouterIdentity(net.i2p.data.router.RouterIdentity) RouterAddress(net.i2p.data.router.RouterAddress) Hash(net.i2p.data.Hash) SigType(net.i2p.crypto.SigType)

Example 22 with RouterAddress

use of net.i2p.data.router.RouterAddress in project i2p.i2p by i2p.

the class UDPTransport method locked_rebuildExternalAddress.

private RouterAddress locked_rebuildExternalAddress(String host, int port, boolean allowRebuildRouterInfo) {
    if (_log.shouldDebug())
        _log.debug("REA4 " + host + ':' + port);
    if (_context.router().isHidden())
        return null;
    OrderedProperties options = new OrderedProperties();
    boolean directIncluded;
    // DNS name assumed IPv4
    boolean isIPv6 = host != null && host.contains(":");
    boolean introducersRequired = (!isIPv6) && introducersRequired();
    if (!introducersRequired && allowDirectUDP() && port > 0 && host != null) {
        options.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
        options.setProperty(UDPAddress.PROP_HOST, host);
        directIncluded = true;
    } else {
        directIncluded = false;
    }
    boolean introducersIncluded = false;
    if (introducersRequired) {
        // intro manager now sorts introducers, so
        // deepEquals() below will not fail even with same introducers.
        // Was only a problem when we had very very few peers to pick from.
        RouterAddress current = getCurrentAddress(isIPv6);
        int found = _introManager.pickInbound(current, options, PUBLIC_RELAY_COUNT);
        if (found > 0) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Direct? " + directIncluded + " reqd? " + introducersRequired + " picked introducers: " + found);
            _introducersSelectedOn = _context.clock().now();
            introducersIncluded = true;
        } else {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Direct? " + directIncluded + " reqd? " + introducersRequired + " no introducers");
        }
    }
    // if we have explicit external addresses, they had better be reachable
    if (introducersRequired)
        options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING);
    else
        options.setProperty(UDPAddress.PROP_CAPACITY, CAP_TESTING_INTRO);
    // MTU since 0.9.2
    int mtu;
    if (host == null) {
        mtu = _mtu;
    } else {
        try {
            InetAddress ia = InetAddress.getByName(host);
            mtu = setMTU(ia);
        } catch (UnknownHostException uhe) {
            mtu = _mtu;
        }
    }
    if (mtu != PeerState.LARGE_MTU)
        options.setProperty(UDPAddress.PROP_MTU, Integer.toString(mtu));
    if (directIncluded || introducersIncluded) {
        // Note that peers won't connect to us without this - see EstablishmentManager
        if (_introKey != null)
            options.setProperty(UDPAddress.PROP_INTRO_KEY, _introKey.toBase64());
        // SSU seems to regulate at about 85%, so make it a little higher.
        // If this is too low, both NTCP and SSU always have incremented cost and
        // the whole mechanism is not helpful.
        int cost = DEFAULT_COST;
        if (ADJUST_COST && !haveCapacity(91))
            cost += CONGESTION_COST_ADJUSTMENT;
        if (introducersIncluded)
            cost += 2;
        if (isIPv6) {
            TransportUtil.IPv6Config config = getIPv6Config();
            if (config == IPV6_PREFERRED)
                cost--;
            else if (config == IPV6_NOT_PREFERRED)
                cost++;
        }
        RouterAddress addr = new RouterAddress(STYLE, options, cost);
        RouterAddress current = getCurrentAddress(isIPv6);
        boolean wantsRebuild = !addr.deepEquals(current);
        // save the external address, even if we didn't publish it
        if (port > 0 && host != null) {
            RouterAddress local;
            if (directIncluded) {
                local = addr;
            } else {
                OrderedProperties localOpts = new OrderedProperties();
                localOpts.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
                localOpts.setProperty(UDPAddress.PROP_HOST, host);
                local = new RouterAddress(STYLE, localOpts, cost);
            }
            replaceCurrentExternalAddress(local, isIPv6);
        }
        if (wantsRebuild) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Address rebuilt: " + addr, new Exception());
            replaceAddress(addr);
            // via CSFI.createAddresses->TM.getAddresses()->updateAddress()->REA
            if (allowRebuildRouterInfo)
                _context.router().rebuildRouterInfo();
        } else {
            addr = null;
        }
        if (!isIPv6)
            _needsRebuild = false;
        return addr;
    } else {
        if (_log.shouldLog(Log.WARN))
            _log.warn("Wanted to rebuild my SSU address, but couldn't specify either the direct or indirect info (needs introducers? " + introducersRequired + ")", new Exception("source"));
        _needsRebuild = true;
        // save the external address, even if we didn't publish it
        if (port > 0 && host != null) {
            OrderedProperties localOpts = new OrderedProperties();
            localOpts.setProperty(UDPAddress.PROP_PORT, String.valueOf(port));
            localOpts.setProperty(UDPAddress.PROP_HOST, host);
            RouterAddress local = new RouterAddress(STYLE, localOpts, DEFAULT_COST);
            replaceCurrentExternalAddress(local, isIPv6);
        }
        if (hasCurrentAddress()) {
            // We must remove current address, otherwise the user will see
            // "firewalled with inbound NTCP enabled" warning in console.
            // Remove the IPv4 address only
            removeAddress(false);
            // via CSFI.createAddresses->TM.getAddresses()->updateAddress()->REA
            if (allowRebuildRouterInfo)
                _context.router().rebuildRouterInfo();
        }
        return null;
    }
}
Also used : IPv6Config(net.i2p.router.transport.TransportUtil.IPv6Config) TransportUtil(net.i2p.router.transport.TransportUtil) UnknownHostException(java.net.UnknownHostException) OrderedProperties(net.i2p.util.OrderedProperties) RouterAddress(net.i2p.data.router.RouterAddress) InetAddress(java.net.InetAddress) SocketException(java.net.SocketException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException)

Example 23 with RouterAddress

use of net.i2p.data.router.RouterAddress in project i2p.i2p by i2p.

the class PublishLocalRouterInfoJob method runJob.

public void runJob() {
    long last = getContext().netDb().getLastRouterInfoPublishTime();
    long now = getContext().clock().now();
    if (last + MIN_PUBLISH_DELAY > now) {
        long delay = getDelay();
        requeue(last + delay - now);
        return;
    }
    RouterInfo oldRI = getContext().router().getRouterInfo();
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Old routerInfo contains " + oldRI.getAddresses().size() + " addresses and " + oldRI.getOptionsMap().size() + " options");
    try {
        List<RouterAddress> oldAddrs = new ArrayList<RouterAddress>(oldRI.getAddresses());
        List<RouterAddress> newAddrs = getContext().commSystem().createAddresses();
        int count = _runCount.incrementAndGet();
        RouterInfo ri = new RouterInfo(oldRI);
        if (_notFirstTime && (count % 4) != 0 && oldAddrs.size() == newAddrs.size()) {
            // 3 times out of 4, we don't republish if everything is the same...
            // If something changed, including the cost, then publish,
            // otherwise don't.
            String newcaps = getContext().router().getCapabilities();
            boolean different = !oldRI.getCapabilities().equals(newcaps);
            if (!different) {
                Comparator<RouterAddress> comp = new AddrComparator();
                Collections.sort(oldAddrs, comp);
                Collections.sort(newAddrs, comp);
                for (int i = 0; i < oldAddrs.size(); i++) {
                    // deepEquals() includes cost
                    if (!oldAddrs.get(i).deepEquals(newAddrs.get(i))) {
                        different = true;
                        break;
                    }
                }
                if (!different) {
                    if (_log.shouldLog(Log.INFO))
                        _log.info("Not republishing early because costs and caps and addresses are the same");
                    requeue(getDelay());
                    return;
                }
            }
            if (_log.shouldLog(Log.INFO))
                _log.info("Republishing early because addresses or costs or caps have changed -" + " oldCaps: " + oldRI.getCapabilities() + " newCaps: " + newcaps + " old:\n" + oldAddrs + "\nnew:\n" + newAddrs);
        }
        ri.setPublished(getContext().clock().now());
        Properties stats = getContext().statPublisher().publishStatistics();
        ri.setOptions(stats);
        ri.setAddresses(newAddrs);
        SigningPrivateKey key = getContext().keyManager().getSigningPrivateKey();
        if (key == null) {
            _log.log(Log.CRIT, "Internal error - signing private key not known?  rescheduling publish for 30s");
            requeue(30 * 1000);
            return;
        }
        ri.sign(key);
        getContext().router().setRouterInfo(ri);
        if (_log.shouldLog(Log.INFO))
            _log.info("Newly updated routerInfo is published with " + stats.size() + "/" + ri.getOptionsMap().size() + " options on " + new Date(ri.getPublished()));
        try {
            // This won't really publish until the netdb is initialized.
            getContext().netDb().publish(ri);
        } catch (IllegalArgumentException iae) {
            _log.log(Log.CRIT, "Error publishing our identity - corrupt? Restart required", iae);
            getContext().router().rebuildNewIdentity();
        }
    } catch (DataFormatException dfe) {
        _log.error("Error signing the updated local router info!", dfe);
    }
    if (_notFirstTime) {
        requeue(getDelay());
    } else {
        requeue(FIRST_TIME_DELAY);
        _notFirstTime = true;
    }
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) ArrayList(java.util.ArrayList) RouterAddress(net.i2p.data.router.RouterAddress) Properties(java.util.Properties) Date(java.util.Date) SigningPrivateKey(net.i2p.data.SigningPrivateKey) DataFormatException(net.i2p.data.DataFormatException)

Example 24 with RouterAddress

use of net.i2p.data.router.RouterAddress in project i2p.i2p by i2p.

the class KademliaNetworkDatabaseFacade method validate.

/**
 * Determine whether this routerInfo will be accepted as valid and current
 * given what we know now.
 *
 * Call this before each use, to check expiration
 *
 * @return reason why the entry is not valid, or null if it is valid
 * @since 0.9.7
 */
String validate(RouterInfo routerInfo) throws IllegalArgumentException {
    long now = _context.clock().now();
    boolean upLongEnough = _context.router().getUptime() > 60 * 60 * 1000;
    // Once we're over MIN_ROUTERS routers, reduce the expiration time down from the default,
    // as a crude way of limiting memory usage.
    // i.e. at 2*MIN_ROUTERS routers the expiration time will be about half the default, etc.
    // And if we're floodfill, we can keep the expiration really short, since
    // we are always getting the latest published to us.
    // As the net grows this won't be sufficient, and we'll have to implement
    // flushing some from memory, while keeping all on disk.
    long adjustedExpiration;
    if (floodfillEnabled())
        adjustedExpiration = ROUTER_INFO_EXPIRATION_FLOODFILL;
    else
        // _kb.size() includes leasesets but that's ok
        adjustedExpiration = Math.min(ROUTER_INFO_EXPIRATION, ROUTER_INFO_EXPIRATION_MIN + ((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * MIN_ROUTERS / (_kb.size() + 1)));
    if (upLongEnough && !routerInfo.isCurrent(adjustedExpiration)) {
        long age = _context.clock().now() - routerInfo.getPublished();
        int existing = _kb.size();
        if (existing >= MIN_REMAINING_ROUTERS) {
            if (_log.shouldLog(Log.INFO))
                _log.info("Expired RI " + routerInfo.getIdentity().getHash(), new Exception());
            return "Peer expired " + DataHelper.formatDuration(age) + " ago";
        } else {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Even though the peer is old, we have only " + existing + " peers left " + routerInfo);
        }
    }
    if (routerInfo.getPublished() > now + 2 * Router.CLOCK_FUDGE_FACTOR) {
        long age = routerInfo.getPublished() - _context.clock().now();
        if (_log.shouldLog(Log.INFO))
            _log.info("Peer " + routerInfo.getIdentity().getHash() + " published their routerInfo in the future?! [" + new Date(routerInfo.getPublished()) + "]", new Exception());
        return "Peer published " + DataHelper.formatDuration(age) + " in the future?!";
    }
    if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_INTRODUCED)) {
        if (routerInfo.getAddresses().isEmpty())
            return "Old peer with no addresses";
        // And even better, catches the case where the router is unreachable but knows no introducers
        if (routerInfo.getCapabilities().indexOf(Router.CAPABILITY_UNREACHABLE) >= 0)
            return "Old peer and thinks it is unreachable";
        // Just check all the addresses, faster than getting just the SSU ones
        for (RouterAddress ra : routerInfo.getAddresses()) {
            // Introducers change often, introducee will ping introducer for 2 hours
            if (ra.getOption("ihost0") != null)
                return "Old peer with SSU Introducers";
        }
    }
    if (upLongEnough && (routerInfo.getPublished() < now - 2 * 24 * 60 * 60 * 1000l)) {
        long age = _context.clock().now() - routerInfo.getPublished();
        return "Peer published " + DataHelper.formatDuration(age) + " ago";
    }
    if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) {
        if (routerInfo.getTargetAddress("NTCP") == null)
            return "Peer published > 75m ago, SSU only without introducers";
    }
    return null;
}
Also used : RouterAddress(net.i2p.data.router.RouterAddress) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException) Date(java.util.Date)

Example 25 with RouterAddress

use of net.i2p.data.router.RouterAddress in project i2p.i2p by i2p.

the class ProfileOrganizer method selectPeersLocallyUnreachable.

/**
 * Get the peers the transport layer thinks are unreachable, and
 * add in the peers with the SSU peer testing bug,
 * and peers requiring introducers.
 */
public List<Hash> selectPeersLocallyUnreachable() {
    List<Hash> n;
    int count;
    getReadLock();
    try {
        count = _notFailingPeers.size();
        n = new ArrayList<Hash>(_notFailingPeers.keySet());
    } finally {
        releaseReadLock();
    }
    List<Hash> l = new ArrayList<Hash>(count / 4);
    for (Hash peer : n) {
        if (_context.commSystem().wasUnreachable(peer))
            l.add(peer);
        else {
            // Blacklist <= 0.6.1.32 SSU-only peers, they don't know if they are unreachable,
            // and we may not know either if they contacted us first, so assume they are.
            // Also blacklist all peers requiring SSU introducers, because either
            // a) it's slow; or
            // b) it doesn't work very often; or
            // c) in the event they are advertising NTCP, it probably won't work because
            // they probably don't have a TCP hole punched in their firewall either.
            RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
            if (info != null) {
                String v = info.getVersion();
                // this only works if there is no 0.6.1.34!
                if ((!v.equals("0.6.1.33")) && v.startsWith("0.6.1.") && info.getTargetAddress("NTCP") == null)
                    l.add(peer);
                else {
                    RouterAddress ra = info.getTargetAddress("SSU");
                    // as long as they have NTCP
                    if (ra == null) {
                        if (info.getTargetAddress("NTCP") == null)
                            l.add(peer);
                        continue;
                    }
                    // This is the quick way of doing UDPAddress.getIntroducerCount() > 0
                    if (ra.getOption("ihost0") != null)
                        l.add(peer);
                }
            }
        }
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug("Unreachable: " + l);
    return l;
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) ArrayList(java.util.ArrayList) RouterAddress(net.i2p.data.router.RouterAddress) Hash(net.i2p.data.Hash)

Aggregations

RouterAddress (net.i2p.data.router.RouterAddress)42 RouterInfo (net.i2p.data.router.RouterInfo)17 Hash (net.i2p.data.Hash)11 IOException (java.io.IOException)9 ArrayList (java.util.ArrayList)9 OrderedProperties (net.i2p.util.OrderedProperties)6 InetAddress (java.net.InetAddress)5 Map (java.util.Map)5 RouterIdentity (net.i2p.data.router.RouterIdentity)5 UnknownHostException (java.net.UnknownHostException)4 HashMap (java.util.HashMap)4 DataFormatException (net.i2p.data.DataFormatException)4 ServerSocketChannel (java.nio.channels.ServerSocketChannel)3 Date (java.util.Date)3 Status (net.i2p.router.CommSystemFacade.Status)3 OutNetMessage (net.i2p.router.OutNetMessage)3 File (java.io.File)2 InetSocketAddress (java.net.InetSocketAddress)2 Properties (java.util.Properties)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)2