package net.tomp2p.holep.manual;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Random;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import net.tomp2p.futures.FutureDone;
import net.tomp2p.holep.NATType;
import net.tomp2p.holep.NATTypeDetection;
import net.tomp2p.p2p.Peer;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
/**
* Add the following lines to sudoers username ALL=(ALL) NOPASSWD:
* <location>/nat-net.sh username ALL=(ALL) NOPASSWD: /usr/bin/ip
*
* Make sure the network namespaces can resolve the hostname, otherwise huge
* delays are to be expected.
*
* This testcase runs on a single machine and tests the two widely used NAT
* settings (port-preserving and symmetric). However, most likely this will
* never run on travis-ci as this requires some extra setup on the machine
* itself. Thus, this test-case is disabled by default and tests have to be
* performed manully.
*
* @author Thomas Bocek
*
*/
//travis-ci cannot test this, the kernel does not support all the required features:
//Perhaps iptables or your kernel needs to be upgraded
//see also here: https://github.com/travis-ci/travis-ci/issues/1341
//@Ignore
public class TestNATHolePunching implements Serializable {
private static final long serialVersionUID = 1L;
final static private Random RND = new Random(42);
//### CHANGE THIS TO YOUR INTERFACE###
final static private String INF = "enp0s25";
static private Number160 relayPeerId = new Number160(RND);
@Before
public void before() throws IOException, InterruptedException {
LocalNATUtils.executeNatSetup("start", "0");
LocalNATUtils.executeNatSetup("start", "1");
}
@After
public void after() throws IOException, InterruptedException {
LocalNATUtils.executeNatSetup("stop", "0");
LocalNATUtils.executeNatSetup("stop", "1");
}
private static FutureDone<NATType> discover(final String address, Peer peer)
throws UnknownHostException {
PeerAddress relayP = PeerAddress.create(relayPeerId, address, 5002, 5002, 5003);
return NATTypeDetection.checkNATType(peer, relayP);
}
private static Serializable discover(FutureDone<NATType> type)
throws UnknownHostException {
return type.isSuccess() ? type.object().name() : type.failedReason();
}
@SuppressWarnings("serial")
@Test
public void testHolePunching() throws Exception {
Peer relayPeer = null;
RemotePeer unr1 = null;
RemotePeer unr2 = null;
try {
relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002);
InetAddress relayAddress = relayPeer.peerAddress().ipv4Socket().ipv4().toInetAddress();
final String address = relayAddress.getHostAddress();
CommandSync sync = new CommandSync(2);
unr1 = LocalNATUtils.executePeer(0, sync,
new Command[] { new Command() {
// startup
@Override
public Serializable execute() throws Exception {
Peer peer = LocalNATUtils.init("10.0.0.2", 5000, 0);
put("peer", peer);
return "initialized " + peer.peerAddress();
}
}, new Command() {
// detect the NAT type
@Override
public Serializable execute() throws Exception {
Peer peer = (Peer) get("peer");
return "TODO";
}
}, new Command() {
//shutdown
@Override
public Serializable execute() throws Exception {
Peer peer = (Peer) get("peer");
return LocalNATUtils.shutdown(peer);
}
} });
unr2 = LocalNATUtils.executePeer(1, sync,
new Command[] { new Command() {
// startup
@Override
public Serializable execute() throws Exception {
Peer peer = LocalNATUtils.init("10.0.1.2", 5001, 1);
put("peer", peer);
return "initialized " + peer.peerAddress();
}
}, new Command() {
// detect the NAT type
@Override
public Serializable execute() throws Exception {
Peer peer = (Peer) get("peer");
FutureDone<NATType> type = discover(address, peer);
return "TODO";
}
}, new Command() {
//shutdown
@Override
public Serializable execute() throws Exception {
Peer peer = (Peer) get("peer");
return LocalNATUtils.shutdown(peer);
}
} });
unr1.waitFor();
unr2.waitFor();
Assert.assertEquals(NATType.PORT_PRESERVING.toString(),
unr1.getResult(1));
Assert.assertEquals(NATType.NON_PRESERVING_OTHER.toString(),
unr2.getResult(1));
} finally {
System.out.print("LOCAL> shutdown.");
LocalNATUtils.shutdown(relayPeer);
System.out.print(".");
LocalNATUtils.shutdown(unr1, unr2);
System.out.println(".");
}
}
}