/* * Copyright 2011 Thomas Bocek * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package net.tomp2p.futures; import java.util.Timer; import java.util.concurrent.TimeUnit; import net.tomp2p.peers.PeerAddress; import net.tomp2p.utils.Timings; /** * The future that keeps track of network discovery such as discovery if its behind a NAT, the status if UPNP or NAT-PMP * could be established, if there is portforwarding. * * @author Thomas Bocek */ public class FutureDiscover extends BaseFutureImpl<FutureDiscover> { // result private PeerAddress ourPeerAddress; private PeerAddress reporter; private boolean discoveredTCP = false; private boolean discoveredUDP = false; private boolean setupRelay = false; /** * Constructor. */ public FutureDiscover() { self(this); } /** * Creates a new future object and creates a timer that fires failed after a timeout. * * @param timer * The timer to use * @param delaySec * The delay in seconds */ public void setTimeout(final Timer timer, final int delaySec) { final DiscoverTimeoutTask task = new DiscoverTimeoutTask(); timer.schedule(task, TimeUnit.SECONDS.toMillis(delaySec)); addListener(new BaseFutureAdapter<FutureDiscover>() { @Override public void operationComplete(final FutureDiscover future) throws Exception { // cancel timeout if we are done. task.cancel(); } }); } /** * Gets called if the discovery was a success and an other peer could ping us with TCP and UDP. * * @param ourPeerAddress * The peerAddress of our server * @param reporter * The peerAddress of the peer that reported our address */ public void done(final PeerAddress ourPeerAddress, final PeerAddress reporter) { // System.err.println("called done"); synchronized (lock) { if (!setCompletedAndNotify()) { return; } this.type = FutureType.OK; this.ourPeerAddress = ourPeerAddress; this.reporter = reporter; } notifyListerenrs(); } /** * The peerAddress where we are reachable. * * @return The new un-firewalled peerAddress of this peer */ public PeerAddress getPeerAddress() { synchronized (lock) { return ourPeerAddress; } } /** * @return The reporter that told us what peer address we have */ public PeerAddress getReporter() { synchronized (lock) { return reporter; } } /** * Intermediate result if TCP has been discovered. Set discoveredTCP True if other peer could reach us with a TCP * ping. */ public void setDiscoveredTCP() { synchronized (lock) { this.discoveredTCP = true; } } /** * Intermediate result if UDP has been discovered. Set discoveredUDP True if other peer could reach us with a UDP * ping. */ public void setDiscoveredUDP() { synchronized (lock) { this.discoveredUDP = true; } } /** * Checks if this peer can be reached via TCP. * * @return True if this peer can be reached via TCP from outside. */ public boolean isDiscoveredTCP() { synchronized (lock) { return discoveredTCP; } } /** * Checks if this peer can be reached via UDP. * * @return True if this peer can be reached via UDP from outside. */ public boolean isDiscoveredUDP() { synchronized (lock) { return discoveredUDP; } } /** * Indicates if a relay could be established. It makes no sense to make a relay, if the peer e.g. is not connected * to the Internet. * * @return True if the user could try to establish a relay connection */ public boolean isSetupRealy() { synchronized (lock) { return setupRelay; } } /** * In case of no peer can contact us, we fire an failed. */ private final class DiscoverTimeoutTask extends java.util.TimerTask { private final long start = Timings.currentTimeMillis(); @Override public void run() { setFailedRelayPossible("Timeout in Discover: " + (Timings.currentTimeMillis() - start) + "ms"); } } /** * Set failed but with a flag that indicates if it makes sense to try to setup a relay. See {@link #isSetupRelay()} * * @param failed * The reason for failure * @return this class */ public FutureDiscover setFailedRelayPossible(final String failed) { synchronized (lock) { if (!setCompletedAndNotify()) { return this; } this.reason = failed; this.type = FutureType.FAILED; this.setupRelay = true; } notifyListerenrs(); return this; } }