From d61a63b37827e1988eb6ab7c3377252290c82113 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 27 May 2015 20:01:50 +0200 Subject: [PATCH 001/135] [maven-release-plugin] prepare for next development iteration --- all/pom.xml | 2 +- android/pom.xml | 2 +- core/pom.xml | 2 +- dht/pom.xml | 2 +- examples/pom.xml | 2 +- nat/pom.xml | 2 +- pom.xml | 4 ++-- replication/pom.xml | 2 +- social/pom.xml | 2 +- storage/pom.xml | 2 +- tracker/pom.xml | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 29461e6e2..e2de6cf95 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -13,7 +13,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-all diff --git a/android/pom.xml b/android/pom.xml index b58285bc1..c6cf79159 100644 --- a/android/pom.xml +++ b/android/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-android diff --git a/core/pom.xml b/core/pom.xml index bb3c8084d..164294d56 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -13,7 +13,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-core diff --git a/dht/pom.xml b/dht/pom.xml index 0f41ac748..10a493b8e 100644 --- a/dht/pom.xml +++ b/dht/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-dht diff --git a/examples/pom.xml b/examples/pom.xml index f2fde3db1..9859d74f8 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-examples diff --git a/nat/pom.xml b/nat/pom.xml index 35599af6f..cf1300e64 100644 --- a/nat/pom.xml +++ b/nat/pom.xml @@ -13,7 +13,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-nat diff --git a/pom.xml b/pom.xml index c6e7fc75e..b1cc47385 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ net.tomp2p tomp2p-parent pom - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT TomP2P http://tomp2p.net @@ -34,7 +34,7 @@ https://github.com/tomp2p/TomP2P scm:git:git://github.com/tomp2p/TomP2P.git scm:git:ssh://git@github.com/tomp2p/TomP2P.git - tomp2p-parent-5.0-Beta8 + HEAD diff --git a/replication/pom.xml b/replication/pom.xml index 971e6323f..171c2b6f9 100644 --- a/replication/pom.xml +++ b/replication/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-replication diff --git a/social/pom.xml b/social/pom.xml index 0110dc237..6d1bc3056 100644 --- a/social/pom.xml +++ b/social/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-social diff --git a/storage/pom.xml b/storage/pom.xml index ba665b379..bad1479fa 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-storage diff --git a/tracker/pom.xml b/tracker/pom.xml index 3059e3597..ea499273b 100644 --- a/tracker/pom.xml +++ b/tracker/pom.xml @@ -20,7 +20,7 @@ net.tomp2p tomp2p-parent - 5.0-Beta8 + 5.0-Beta9-SNAPSHOT tomp2p-tracker From b6cfacdad3cfa2d377364441eebf6d30b9c665da Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 1 Jun 2015 13:25:33 +0200 Subject: [PATCH 002/135] fixed #105 --- .../test/java/net/tomp2p/dht/TestStorage.java | 22 +++++++++++++++++++ .../net/tomp2p/storage/DataSerializer.java | 3 +++ .../java/net/tomp2p/storage/TestStorage.java | 22 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorage.java b/dht/src/test/java/net/tomp2p/dht/TestStorage.java index 4e2bf0efe..43cd7c76e 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorage.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorage.java @@ -10,6 +10,7 @@ import java.util.SortedMap; import java.util.concurrent.atomic.AtomicInteger; +import net.tomp2p.connection.DSASignatureFactory; import net.tomp2p.dht.StorageLayer.PutStatus; import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; @@ -348,6 +349,27 @@ private void testPublicKeyDomain(StorageLayer storage) throws Exception { Assert.assertEquals(PutStatus.FAILED_SECURITY, result2); } + @Test + public void testSecurity() throws Exception { + Storage storageM = createStorage(); + testSecurity(new StorageLayer(storageM)); + storageM.close(); + } + + private void testSecurity(StorageLayer storage) throws Exception { + KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); + KeyPair pair1 = gen.generateKeyPair(); + Data test = new Data("test-security"); + test.signNow(pair1.getPrivate(), new DSASignatureFactory()); + + Enum result1 = storage.put(key3, test, + pair1.getPublic(), false, false, false); + Assert.assertEquals(PutStatus.OK, result1); + Data data = storage.get(key3); + + Assert.assertEquals(test, data); + } + @Test public void testConcurrency() throws InterruptedException, IOException { final Storage sM = createStorage(); diff --git a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java index eb535b949..0af8fdf39 100644 --- a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java +++ b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java @@ -148,6 +148,9 @@ private Data deserializeMapDB(DataInput in) throws IOException { if(!retVal) { throw new IOException("data could not be read"); } + me = new byte[signatureFactory.signatureSize()]; + in.readFully(me); + buf = Unpooled.wrappedBuffer(me); retVal = data.decodeDone(buf, signatureFactory); if(!retVal) { throw new IOException("signature could not be read"); diff --git a/storage/src/test/java/net/tomp2p/storage/TestStorage.java b/storage/src/test/java/net/tomp2p/storage/TestStorage.java index bebec1129..31dcda430 100644 --- a/storage/src/test/java/net/tomp2p/storage/TestStorage.java +++ b/storage/src/test/java/net/tomp2p/storage/TestStorage.java @@ -10,6 +10,7 @@ import java.util.SortedMap; import java.util.concurrent.CountDownLatch; +import net.tomp2p.connection.DSASignatureFactory; import net.tomp2p.dht.Storage; import net.tomp2p.dht.StorageLayer; import net.tomp2p.dht.StorageLayer.PutStatus; @@ -357,6 +358,27 @@ private void testPublicKeyDomain(StorageLayer storage) throws Exception { Assert.assertEquals(PutStatus.FAILED_SECURITY, result2); } + @Test + public void testSecurity() throws Exception { + Storage storageM = createStorage(); + testSecurity(new StorageLayer(storageM)); + storageM.close(); + } + + private void testSecurity(StorageLayer storage) throws Exception { + KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); + KeyPair pair1 = gen.generateKeyPair(); + Data test = new Data("test-security"); + test.signNow(pair1.getPrivate(), new DSASignatureFactory()); + + Enum result1 = storage.put(key3, test, + pair1.getPublic(), false, false, false); + Assert.assertEquals(PutStatus.OK, result1); + Data data = storage.get(key3); + + Assert.assertEquals(test, data); + } + @Test public void testConcurrency() throws InterruptedException, IOException { final Storage sM = createStorage(); From 6ec03d49fddbe292c6a1f0630dfc171632ba369c Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 4 Jun 2015 15:56:30 +0200 Subject: [PATCH 003/135] better memory managemnt. Clear distinction between direct and heap buffer. The current approach does not work well with constrained devices. --- .../java/net/tomp2p/connection/Sender.java | 9 +- .../main/java/net/tomp2p/message/Buffer.java | 118 ++++----------- .../net/tomp2p/message/DataFilterTTL.java | 3 +- .../main/java/net/tomp2p/message/Encoder.java | 27 +--- .../tomp2p/p2p/builder/SendDirectBuilder.java | 12 +- .../java/net/tomp2p/rpc/DirectDataRPC.java | 3 +- .../net/tomp2p/rpc/SendDirectBuilderI.java | 4 +- .../main/java/net/tomp2p/storage/Data.java | 40 ++--- .../java/net/tomp2p/storage/DataBuffer.java | 138 ++++++++++++----- .../java/net/tomp2p/dht/CumulativeScheme.java | 5 +- .../net/tomp2p/dht/DistributedHashTable.java | 24 ++- .../net/tomp2p/dht/EvaluatingSchemeDHT.java | 5 +- .../main/java/net/tomp2p/dht/FutureDHT.java | 6 + .../main/java/net/tomp2p/dht/FutureGet.java | 11 ++ .../java/net/tomp2p/dht/FutureRemove.java | 11 ++ .../main/java/net/tomp2p/dht/FutureSend.java | 20 ++- .../main/java/net/tomp2p/dht/PutBuilder.java | 16 +- .../main/java/net/tomp2p/dht/SendBuilder.java | 12 +- dht/src/main/java/net/tomp2p/dht/Storage.java | 2 +- .../java/net/tomp2p/dht/StorageLayer.java | 134 +++++++++------- .../java/net/tomp2p/dht/StorageMemory.java | 143 +++--------------- .../main/java/net/tomp2p/dht/UtilsDHT.java | 13 +- .../java/net/tomp2p/dht/VotingSchemeDHT.java | 5 +- dht/src/test/java/net/tomp2p/dht/TestDHT.java | 51 ++++++- dht/src/test/java/net/tomp2p/dht/TestH2H.java | 4 +- .../java/net/tomp2p/dht/TestStorageDHT.java | 6 +- .../java/net/tomp2p/storage/StorageDisk.java | 93 +----------- 27 files changed, 397 insertions(+), 518 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 8ff5b5557..93adfc727 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -418,13 +418,12 @@ public void sendSelf(final FutureResponse futureResponse, final Message message) Message copy = message.duplicate(new DataFilter() { @Override public Data filter(Data data, boolean isConvertMeta, boolean isReply) { - Data copyData = data.duplicate(); - if (copyData.isSigned() && copyData.signature() == null) { - copyData.protectEntry(message.privateKey()); + if (data.isSigned() && data.signature() == null) { + data.protectEntry(message.privateKey()); } // set new valid from as this data item might have an old one - copyData.validFromMillis(System.currentTimeMillis()); - return copyData; + data.validFromMillis(System.currentTimeMillis()); + return data; } }); diff --git a/core/src/main/java/net/tomp2p/message/Buffer.java b/core/src/main/java/net/tomp2p/message/Buffer.java index 6b392bc35..6afcc10a0 100644 --- a/core/src/main/java/net/tomp2p/message/Buffer.java +++ b/core/src/main/java/net/tomp2p/message/Buffer.java @@ -1,109 +1,57 @@ package net.tomp2p.message; import io.netty.buffer.ByteBuf; -import io.netty.buffer.CompositeByteBuf; import java.io.IOException; import net.tomp2p.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class Buffer { - - private static final Logger LOG = LoggerFactory.getLogger(Buffer.class); - - private final ByteBuf buffer; - private final int length; - - private int read = 0; - public Buffer(final ByteBuf buffer, final int length) { - this.buffer = buffer; - this.length = length; - } + private final ByteBuf buffer; + private final int length; - public Buffer(ByteBuf buffer) { - this.buffer = buffer; - this.length = buffer.readableBytes(); - } + private int read = 0; - public int length() { - return length; - } + public Buffer(final ByteBuf buffer, final int length) { + this.buffer = buffer; + this.length = length; + } - public ByteBuf buffer() { - return buffer; - } + public Buffer(ByteBuf buffer) { + this.buffer = buffer; + this.length = buffer.readableBytes(); + } - public int readable() { - int remaining = length - read; - int available = buffer.readableBytes(); - return Math.min(remaining, available); - } - - public boolean isComplete() { - return length == buffer.readableBytes(); - } + public int length() { + return length; + } - public int incRead(final int read) { - this.read += read; - return this.read; - } + public ByteBuf buffer() { + return buffer; + } - public boolean done() { - return this.read == length; - } + public int readable() { + int remaining = length - read; + int available = buffer.readableBytes(); + return Math.min(remaining, available); + } - public int alreadyRead() { - return read; - } + public boolean isComplete() { + return length == buffer.readableBytes(); + } - public Buffer addComponent(final ByteBuf slice) { - if (buffer instanceof CompositeByteBuf) { - CompositeByteBuf cbb = (CompositeByteBuf) buffer; - slice.retain(); - cbb.addComponent(slice); - cbb.writerIndex(cbb.writerIndex() + slice.readableBytes()); - } else { - buffer.writeBytes(slice); - LOG.debug("Buffer copied. You can use a CompositeByteBuf"); - } - return this; - } - - public Object object() throws ClassNotFoundException, IOException { - return Utils.decodeJavaObject(buffer.duplicate().readerIndex(0)); - } - - @Override - protected void finalize() throws Throwable { - buffer.release(); - } - - @Override - public int hashCode() { - return buffer.duplicate().readerIndex(0).hashCode() ^ length; - } + public int incRead(final int read) { + this.read += read; + return this.read; + } - @Override - public boolean equals(final Object obj) { - if (!(obj instanceof Buffer)) { - return false; - } - if (obj == this) { - return true; - } - final Buffer b = (Buffer) obj; - if(b.length != length) { - return false; - } - return b.buffer.duplicate().readerIndex(0).equals(buffer.duplicate().readerIndex(0)); - } + public Object object() throws ClassNotFoundException, IOException { + return Utils.decodeJavaObject(buffer.duplicate().readerIndex(0)); + } public void reset() { - read=0; + read = 0; buffer.resetReaderIndex(); } } diff --git a/core/src/main/java/net/tomp2p/message/DataFilterTTL.java b/core/src/main/java/net/tomp2p/message/DataFilterTTL.java index 1be155d1e..63acca10e 100644 --- a/core/src/main/java/net/tomp2p/message/DataFilterTTL.java +++ b/core/src/main/java/net/tomp2p/message/DataFilterTTL.java @@ -9,8 +9,9 @@ public Data filter(Data data, boolean isConvertMeta, boolean isReply) { final Data copyData; if(isConvertMeta) { copyData = data.duplicateMeta(); + data.release(); } else { - copyData = data.duplicate(); + copyData = data; } if(isReply) { int ttl = (int) ((copyData.expirationMillis() - System.currentTimeMillis()) / 1000); diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index b3730f15c..8864c906e 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -149,13 +149,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException buf.writeBytes(dataMap.domainKey().toByteArray()); buf.writeBytes(entry.getKey().toByteArray()); buf.writeBytes(dataMap.versionKey().toByteArray()); - synchronized (entry.getValue().lockObject()) { - if(entry.getValue().isReleased()) { - encodeData(buf, new Data(), dataMap.isConvertMeta(), !message.isRequest()); - } else { - encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); - } - } + encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); } } else { for (Entry entry : dataMap.dataMap().entrySet()) { @@ -163,13 +157,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException buf.writeBytes(entry.getKey().domainKey().toByteArray()); buf.writeBytes(entry.getKey().contentKey().toByteArray()); buf.writeBytes(entry.getKey().versionKey().toByteArray()); - synchronized (entry.getValue().lockObject()) { - if(entry.getValue().isReleased()) { - encodeData(buf, new Data(), dataMap.isConvertMeta(), !message.isRequest()); - } else { - encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); - } - } + encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); } } message.contentReferences().poll(); @@ -254,13 +242,10 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException } private void encodeData(AlternativeCompositeByteBuf buf, Data data, boolean isConvertMeta, boolean isReply) throws InvalidKeyException, SignatureException, IOException { - Data copyData = dataFilterTTL.filter(data, isConvertMeta, isReply); - copyData.encodeHeader(buf, signatureFactory); - copyData.encodeBuffer(buf); - copyData.encodeDone(buf, signatureFactory, message.privateKey()); - if(copyData.isReleaseAfterSend()) { - copyData.release(); - } + Data filteredData = dataFilterTTL.filter(data, isConvertMeta, isReply); + filteredData.encodeHeader(buf, signatureFactory); + filteredData.encodeBuffer(buf); + filteredData.encodeDone(buf, signatureFactory, message.privateKey()); } public Message message() { diff --git a/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java index db898a6c5..552871eae 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java @@ -27,10 +27,10 @@ import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Buffer; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.SendDirectBuilderI; +import net.tomp2p.storage.DataBuffer; import net.tomp2p.utils.Utils; public class SendDirectBuilder implements ConnectionConfiguration, SendDirectBuilderI, @@ -41,7 +41,7 @@ public class SendDirectBuilder implements ConnectionConfiguration, SendDirectBui private final PeerAddress recipientAddress; - private Buffer buffer; + private DataBuffer dataBuffer; private FuturePeerConnection recipientConnection; private PeerConnection peerConnection; @@ -85,12 +85,12 @@ public PeerAddress recipient() { return recipientAddress; } - public Buffer buffer() { - return buffer; + public DataBuffer dataBuffer() { + return dataBuffer; } - public SendDirectBuilder buffer(Buffer buffer) { - this.buffer = buffer; + public SendDirectBuilder dataBuffer(DataBuffer dataBuffer) { + this.dataBuffer = dataBuffer; return this; } diff --git a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java index c274e1eef..ce84309da 100644 --- a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java @@ -65,7 +65,8 @@ public RequestHandler sendInternal(final PeerAddress remotePeer, message.streaming(sendDirectBuilder.isStreaming()); if (sendDirectBuilder.isRaw()) { - message.buffer(sendDirectBuilder.buffer()); + Buffer buffer = new Buffer(sendDirectBuilder.dataBuffer().toByteBuf()); + message.buffer(buffer); } else { byte[] me; try { diff --git a/core/src/main/java/net/tomp2p/rpc/SendDirectBuilderI.java b/core/src/main/java/net/tomp2p/rpc/SendDirectBuilderI.java index 5ecce6018..8c6369fbf 100644 --- a/core/src/main/java/net/tomp2p/rpc/SendDirectBuilderI.java +++ b/core/src/main/java/net/tomp2p/rpc/SendDirectBuilderI.java @@ -3,7 +3,7 @@ import java.security.KeyPair; import net.tomp2p.connection.ConnectionConfiguration; -import net.tomp2p.message.Buffer; +import net.tomp2p.storage.DataBuffer; public interface SendDirectBuilderI extends ConnectionConfiguration { @@ -13,7 +13,7 @@ public interface SendDirectBuilderI extends ConnectionConfiguration { boolean isStreaming(); - Buffer buffer(); + DataBuffer dataBuffer(); Object object(); diff --git a/core/src/main/java/net/tomp2p/storage/Data.java b/core/src/main/java/net/tomp2p/storage/Data.java index d9b573ea5..31ff0a2d1 100644 --- a/core/src/main/java/net/tomp2p/storage/Data.java +++ b/core/src/main/java/net/tomp2p/storage/Data.java @@ -83,8 +83,6 @@ public enum Type {SMALL, LARGE} private SignatureFactory signatureFactory; private Number160 hash; private boolean meta; - private boolean releaseAfterSend; - private boolean released = false; public Data(final DataBuffer buffer) { this(buffer, buffer.length()); @@ -469,7 +467,11 @@ public ByteBuf buffer() { } public Object object() throws ClassNotFoundException, IOException { - return Utils.decodeJavaObject(buffer); + if(buffer.isHeapBuffer()) { + return Utils.decodeJavaObject(buffer.bytes(), 0, buffer.bytes().length); + } else { + return Utils.decodeJavaObject(buffer); + } } public long validFromMillis() { @@ -713,20 +715,6 @@ public Data meta() { this.meta = true; return this; } - - public boolean isReleaseAfterSend() { - return releaseAfterSend; - } - - public Data releaseAfterSend(boolean releaseAfterSend) { - this.releaseAfterSend = releaseAfterSend; - return this; - } - - public Data releaseAfterSend() { - this.releaseAfterSend = true; - return this; - } @Override public String toString() { @@ -761,7 +749,6 @@ public Data duplicate() { data.privateKey = privateKey; data.validFromMillis = validFromMillis; data.prepareFlag = prepareFlag; - data.releaseAfterSend = releaseAfterSend; return data; } @@ -783,7 +770,6 @@ public Data duplicateMeta() { data.privateKey = privateKey; data.validFromMillis = validFromMillis; data.prepareFlag = prepareFlag; - data.releaseAfterSend = releaseAfterSend; return data; } @@ -915,18 +901,16 @@ public Number160 hash() { public Data release() { synchronized (buffer.lockObject()) { - released = true; buffer.release(); } return this; } - - public Object lockObject() { - return buffer.lockObject(); - } - - public boolean isReleased() { - return released; - } + public String refcnt() { + return buffer.refcnt(); + } + + public boolean isHeapBuffer() { + return buffer.isHeapBuffer(); + } } diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index fd99504f6..060aeb2dd 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -10,7 +10,9 @@ public class DataBuffer { + private final Object lock = new Object(); private final List buffers; + private byte[] heapBuffer = null; public DataBuffer() { this(1); @@ -58,7 +60,10 @@ private DataBuffer(final List buffers) { } public DataBuffer add(DataBuffer dataBuffer) { - synchronized (dataBuffer.buffers) { + if(isHeapBuffer()) { + throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + } + synchronized (dataBuffer.lock) { for (final ByteBuf buf : dataBuffer.buffers) { if(buf.isReadable()) { this.buffers.add(buf.duplicate()); @@ -74,8 +79,11 @@ public DataBuffer add(DataBuffer dataBuffer) { * @return Shallow copy of this DataBuffer. */ public DataBuffer shallowCopy() { + if(isHeapBuffer()) { + throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + } final DataBuffer db; - synchronized (buffers) { + synchronized (lock) { db = new DataBuffer(buffers); } return db; @@ -88,14 +96,19 @@ public DataBuffer shallowCopy() { * @return The backing list of byte buffers */ public List bufferList() { - final DataBuffer copy = shallowCopy(); - final List nioBuffers = new ArrayList( - copy.buffers.size()); - for (final ByteBuf buf : copy.buffers) { - for (final ByteBuffer bb : buf.nioBuffers()) { - nioBuffers.add(bb); + final List nioBuffers; + if(isHeapBuffer()) { + nioBuffers = new ArrayList(1); + nioBuffers.add(ByteBuffer.wrap(heapBuffer)); + } else { + final DataBuffer copy = shallowCopy(); + nioBuffers = new ArrayList(copy.buffers.size()); + for (final ByteBuf buf : copy.buffers) { + for (final ByteBuffer bb : buf.nioBuffers()) { + nioBuffers.add(bb); + } } - } + } return nioBuffers; } @@ -103,12 +116,16 @@ public List bufferList() { * @return The length of the data that is backed by the data buffer */ public int length() { - int length = 0; - final DataBuffer copy = shallowCopy(); - for (final ByteBuf buffer : copy.buffers) { - length += buffer.writerIndex(); + if(isHeapBuffer()) { + return heapBuffer.length; + } else { + int length = 0; + final DataBuffer copy = shallowCopy(); + for (final ByteBuf buffer : copy.buffers) { + length += buffer.writerIndex(); + } + return length; } - return length; } /** @@ -116,8 +133,12 @@ public int length() { * not deep copied here. */ public ByteBuf toByteBuf() { - final DataBuffer copy = shallowCopy(); - return Unpooled.wrappedBuffer(copy.buffers.toArray(new ByteBuf[0])); + if(isHeapBuffer()) { + return Unpooled.wrappedBuffer(heapBuffer); + } else { + final DataBuffer copy = shallowCopy(); + return Unpooled.wrappedBuffer(copy.buffers.toArray(new ByteBuf[0])); + } } /** @@ -125,8 +146,12 @@ public ByteBuf toByteBuf() { * not deep copied here. */ public ByteBuf[] toByteBufs() { - final DataBuffer copy = shallowCopy(); - return copy.buffers.toArray(new ByteBuf[0]); + if(isHeapBuffer()) { + return new ByteBuf[]{toByteBuf()}; + } else { + final DataBuffer copy = shallowCopy(); + return copy.buffers.toArray(new ByteBuf[0]); + } } /** @@ -137,6 +162,9 @@ public ByteBuf[] toByteBufs() { * transfered to */ public int transferTo(final AlternativeCompositeByteBuf buf) { + if(isHeapBuffer()) { + throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + } final DataBuffer copy = shallowCopy(); int transferred = 0; for (final ByteBuf buffer : copy.buffers) { @@ -147,6 +175,9 @@ public int transferTo(final AlternativeCompositeByteBuf buf) { } public int transferFrom(final ByteBuf buf, final int max) { + if(isHeapBuffer()) { + throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + } final int readable = buf.readableBytes(); final int index = buf.readerIndex(); final int length = Math.min(max, readable); @@ -162,7 +193,7 @@ public int transferFrom(final ByteBuf buf, final int max) { for (final ByteBuf decom : decoms) { if(decom.isReadable()) { - synchronized (buffers) { + synchronized (lock) { // this is already a slice buffers.add(decom); } @@ -174,7 +205,7 @@ public int transferFrom(final ByteBuf buf, final int max) { } else { final ByteBuf slice = buf.slice(index, length); if(slice.isReadable()) { - synchronized (buffers) { + synchronized (lock) { buffers.add(slice); } transferred += slice.readableBytes(); @@ -188,6 +219,7 @@ public int transferFrom(final ByteBuf buf, final int max) { @Override public int hashCode() { + //convert to heap buffer return Arrays.hashCode(bytes()); } @@ -200,10 +232,11 @@ public boolean equals(final Object obj) { return true; } final DataBuffer m = (DataBuffer) obj; + //convert to heap buffer return Arrays.equals(m.bytes(), bytes()); } - @Override + /*@Override protected void finalize() throws Throwable { // work on the original buffer, no worries about threading as we are the // finalizer @@ -216,7 +249,7 @@ protected void finalize() throws Throwable { } finally { super.finalize(); } - } + }*/ /** * If you plan to use PooledByteBufAlloc, then its important to release the @@ -232,33 +265,64 @@ protected void finalize() throws Throwable { * @return The data buffer */ public DataBuffer release() { - synchronized (buffers) { - for (ByteBuf buf : buffers) { - buf.release(); - } - buffers.clear(); + synchronized (lock) { + releaseIntern(); + } + return this; + } + + private DataBuffer releaseIntern() { + for (ByteBuf buf : buffers) { + buf.release(); } + buffers.clear(); return this; } + + public boolean isHeapBuffer() { + synchronized (lock) { + return heapBuffer != null && buffers.size() == 0; + } + } + /** + * Converts the ByteBuf (most likely a direct buffer) to a heap buffer. Once + * its converted it most of the methods for manipulating the data in this + * class will not work + */ public byte[] bytes() { final List bufs = bufferList(); int size = 0; - for (ByteBuffer buf:bufs) { + for (ByteBuffer buf : bufs) { size += buf.remaining(); } - - final byte[] retVal = new byte[size]; - int offset = 0; - for (ByteBuffer bb:bufs) { - final int length = bb.remaining(); - bb.get(retVal, offset, length); - offset += length; + synchronized (lock) { + if (isHeapBuffer()) { + return heapBuffer; + } + + heapBuffer = new byte[size]; + int offset = 0; + for (ByteBuffer bb : bufs) { + final int length = bb.remaining(); + bb.get(heapBuffer, offset, length); + offset += length; + } + releaseIntern(); + return heapBuffer; } - return retVal; } public Object lockObject() { - return buffers; + return lock; } + + public String refcnt() { + ByteBuf b = buffers.get(0); + if(b != null) { + return ""+b.refCnt(); + + } + return ""; + } } diff --git a/dht/src/main/java/net/tomp2p/dht/CumulativeScheme.java b/dht/src/main/java/net/tomp2p/dht/CumulativeScheme.java index ab5089165..de45ded3c 100644 --- a/dht/src/main/java/net/tomp2p/dht/CumulativeScheme.java +++ b/dht/src/main/java/net/tomp2p/dht/CumulativeScheme.java @@ -15,8 +15,6 @@ */ package net.tomp2p.dht; -import io.netty.buffer.ByteBuf; - import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -28,6 +26,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.DigestResult; import net.tomp2p.storage.Data; +import net.tomp2p.storage.DataBuffer; public class CumulativeScheme implements EvaluatingSchemeDHT { @Override @@ -63,7 +62,7 @@ public Object evaluate3(Map rawKeys) { } @Override - public ByteBuf evaluate4(Map rawKeys) { + public DataBuffer evaluate4(Map rawKeys) { throw new UnsupportedOperationException("cannot cumulate"); } diff --git a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java index 05aa6222c..e9d7a7bf7 100644 --- a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java +++ b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java @@ -15,8 +15,6 @@ */ package net.tomp2p.dht; -import io.netty.buffer.ByteBuf; - import java.io.IOException; import java.util.Collection; import java.util.HashMap; @@ -51,6 +49,7 @@ import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.SimpleBloomFilter; import net.tomp2p.storage.Data; +import net.tomp2p.storage.DataBuffer; import net.tomp2p.utils.Utils; import org.slf4j.Logger; @@ -164,7 +163,7 @@ public void operationComplete(FutureRouting futureRouting) throws Exception { EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), futureDHT, builder.isCancelOnFinish(), future.channelCreator(), new OperationMapper() { - Map rawChannels = new HashMap(); + Map rawChannels = new HashMap(); Map rawObjects = new HashMap(); @@ -189,7 +188,7 @@ public void interMediateResponse(FutureResponse future) { if (future.isSuccess() && future.responseMessage().isOk()) { if (builder.isRaw()) { rawChannels.put(future.request().recipient(), - future.responseMessage().buffer(0).buffer()); + new DataBuffer(future.responseMessage().buffer(0).buffer())); } else { try { rawObjects.put( @@ -223,10 +222,7 @@ public void interMediateResponse(FutureResponse future) { return futureDHT; } - public FuturePut put(final PutBuilder putBuilder) { - final int dataSize = UtilsDHT.dataSize(putBuilder); - final FuturePut futureDHT = new FuturePut(putBuilder, putBuilder.requestP2PConfiguration() - .minimumResults(), dataSize); + public FuturePut put(final PutBuilder putBuilder, final FuturePut futurePut) { putBuilder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FutureChannelCreator future) throws Exception { @@ -235,7 +231,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio final RoutingBuilder routingBuilder = createBuilder(putBuilder); final FutureRouting futureRouting = routing.route(routingBuilder, Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futurePut.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FutureRouting futureRouting) throws Exception { @@ -244,7 +240,7 @@ public void operationComplete(final FutureRouting futureRouting) throws Exceptio futureRouting.potentialHits()); parallelRequests(putBuilder.requestP2PConfiguration(), - EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), futureDHT, false, + EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), futurePut, false, future.channelCreator(), new OperationMapper() { Map> rawData = new HashMap>(); @@ -290,17 +286,17 @@ public void interMediateResponse(final FutureResponse future) { } }); } else { - futureDHT.failed(futureRouting); + futurePut.failed(futureRouting); } } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futurePut.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futurePut.failed(future); } } }); - return futureDHT; + return futurePut; } public FutureGet get(final GetBuilder builder) { diff --git a/dht/src/main/java/net/tomp2p/dht/EvaluatingSchemeDHT.java b/dht/src/main/java/net/tomp2p/dht/EvaluatingSchemeDHT.java index 1aad2def8..38e8f4469 100644 --- a/dht/src/main/java/net/tomp2p/dht/EvaluatingSchemeDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/EvaluatingSchemeDHT.java @@ -15,8 +15,6 @@ */ package net.tomp2p.dht; -import io.netty.buffer.ByteBuf; - import java.util.Collection; import java.util.Map; @@ -25,6 +23,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.DigestResult; import net.tomp2p.storage.Data; +import net.tomp2p.storage.DataBuffer; public interface EvaluatingSchemeDHT { public Collection evaluate1(Map> rawKeys480); @@ -33,7 +32,7 @@ public interface EvaluatingSchemeDHT { public Object evaluate3(Map rawObjects); - public ByteBuf evaluate4(Map rawChannels); + public DataBuffer evaluate4(Map rawChannels); public DigestResult evaluate5(Map rawDigest); diff --git a/dht/src/main/java/net/tomp2p/dht/FutureDHT.java b/dht/src/main/java/net/tomp2p/dht/FutureDHT.java index ef7b4a67a..a31acb732 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureDHT.java @@ -71,6 +71,12 @@ public K addRequests(final FutureResponse futureResponse) { } return self(); } + + public List requests() { + synchronized (lock) { + return requests; + } + } /** * Adds a listener to the response future and releases all aquired channels in channel creator. diff --git a/dht/src/main/java/net/tomp2p/dht/FutureGet.java b/dht/src/main/java/net/tomp2p/dht/FutureGet.java index bcde5abd4..b65e44394 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureGet.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureGet.java @@ -47,6 +47,8 @@ public class FutureGet extends FutureDHT { // Flag indicating if the minimum operations for put have been reached. private boolean minReached; + + private boolean convertToHeapBuffer = true; /** * Default constructor. @@ -86,6 +88,15 @@ public void receivedData(final Map> rawData, f return; } this.rawData = rawData; + + if(convertToHeapBuffer) { + for(Map map:rawData.values()) { + for(Data data:map.values()) { + data.toBytes(); + } + } + } + this.rawDigest = rawDigest; this.rawStatus = rawStatus; this.futuresCompleted = futuresCompleted; diff --git a/dht/src/main/java/net/tomp2p/dht/FutureRemove.java b/dht/src/main/java/net/tomp2p/dht/FutureRemove.java index ac716a462..c4c1e89b0 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureRemove.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureRemove.java @@ -44,6 +44,8 @@ public class FutureRemove extends FutureDHT { private Map result; + private boolean convertToHeapBuffer = true; + /** * Default constructor. */ @@ -124,6 +126,15 @@ public void receivedData(final Map> rawData, F return; } this.rawData = rawData; + + if(convertToHeapBuffer) { + for(Map map:rawData.values()) { + for(Data data:map.values()) { + data.toBytes(); + } + } + } + this.futuresCompleted = futuresCompleted; final int size = rawData.size(); this.type = size > 0 ? FutureType.OK : FutureType.FAILED; diff --git a/dht/src/main/java/net/tomp2p/dht/FutureSend.java b/dht/src/main/java/net/tomp2p/dht/FutureSend.java index f12141854..55c964892 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureSend.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureSend.java @@ -15,12 +15,11 @@ */ package net.tomp2p.dht; -import io.netty.buffer.ByteBuf; - import java.util.Map; import net.tomp2p.futures.FutureDone; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.storage.DataBuffer; /** * The future object for put() operations including routing. @@ -38,10 +37,12 @@ public class FutureSend extends FutureDHT { // Storage of results private Map rawObjects; - private Map rawChannels; + private Map rawChannels; // Flag indicating if the minimum operations for put have been reached. private boolean minReached; + + private boolean convertToHeapBuffer = true; /** * Default constructor. @@ -72,12 +73,19 @@ public FutureSend(final DHTBuilder builder, final int min, final EvaluatingSc * The raw data that have been sent directly with information on which peer it has been sent * @param futuresCompleted */ - public void directData1(final Map rawChannels, FutureDone futuresCompleted) { + public void directData1(final Map rawChannels, FutureDone futuresCompleted) { synchronized (lock) { if (!completedAndNotify()) { return; } this.rawChannels = rawChannels; + + if(convertToHeapBuffer) { + for(DataBuffer data:rawChannels.values()) { + data.bytes(); + } + } + this.futuresCompleted = futuresCompleted; final int size = rawChannels.size(); this.minReached = size >= min; @@ -116,7 +124,7 @@ public void directData2(final Map rawObjects, FutureDone rawDirectData1() { + public Map rawDirectData1() { synchronized (lock) { return rawChannels; } @@ -151,7 +159,7 @@ public Object object() { * * @return The data that have been received. */ - public ByteBuf channelBuffer() { + public DataBuffer channelBuffer() { synchronized (lock) { return this.evaluationScheme.evaluate4(rawChannels); } diff --git a/dht/src/main/java/net/tomp2p/dht/PutBuilder.java b/dht/src/main/java/net/tomp2p/dht/PutBuilder.java index 54599b6fa..29cece373 100644 --- a/dht/src/main/java/net/tomp2p/dht/PutBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/PutBuilder.java @@ -219,6 +219,20 @@ public FuturePut start() { versionKey = Number160.ZERO; } - return peer.distributedHashTable().put(this); + final FuturePut futurePut = new FuturePut(this, requestP2PConfiguration().minimumResults(), dataSize()); + return peer.distributedHashTable().put(this, futurePut); + } + + private int dataSize() { + if(isPutMeta() && changePublicKey()!=null) { + //we only send a marker + return 1; + } else if (isPutConfirm()) { + return 1; + } else if(dataMap()!=null) { + return dataMap().size(); + } else { + return dataMapContent().size(); + } } } diff --git a/dht/src/main/java/net/tomp2p/dht/SendBuilder.java b/dht/src/main/java/net/tomp2p/dht/SendBuilder.java index 794aaced0..a76958cb2 100644 --- a/dht/src/main/java/net/tomp2p/dht/SendBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/SendBuilder.java @@ -16,16 +16,16 @@ package net.tomp2p.dht; -import net.tomp2p.message.Buffer; import net.tomp2p.peers.Number160; import net.tomp2p.rpc.SendDirectBuilderI; +import net.tomp2p.storage.DataBuffer; public class SendBuilder extends DHTBuilder implements SendDirectBuilderI { private final static FutureSend FUTURE_SHUTDOWN = new FutureSend(null) .failed("send builder - peer is shutting down"); - private Buffer buffer; + private DataBuffer dataBuffer; private Object object; @@ -39,12 +39,12 @@ public SendBuilder(PeerDHT peer, Number160 locationKey) { self(this); } - public Buffer buffer() { - return buffer; + public DataBuffer dataBuffer() { + return dataBuffer; } - public SendBuilder buffer(Buffer buffer) { - this.buffer = buffer; + public SendBuilder dataBuffer(DataBuffer dataBuffer) { + this.dataBuffer = dataBuffer; return this; } diff --git a/dht/src/main/java/net/tomp2p/dht/Storage.java b/dht/src/main/java/net/tomp2p/dht/Storage.java index 8b64a2db1..1ba21efae 100644 --- a/dht/src/main/java/net/tomp2p/dht/Storage.java +++ b/dht/src/main/java/net/tomp2p/dht/Storage.java @@ -53,7 +53,7 @@ public interface Storage { public abstract NavigableMap remove(Number640 from, Number640 to); - public abstract NavigableMap subMap(Number640 from, Number640 to, int limit, boolean ascending); + public abstract NavigableMap subMap(Number640 from, Number640 to); public abstract NavigableMap map(); diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 81ee1fc08..af9c33787 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -82,9 +82,16 @@ public enum PutStatus { final private RangeLock responsibilityLock = new RangeLock(); final private Storage backend; + final int maxVersions; public StorageLayer(Storage backend) { this.backend = backend; + this.maxVersions = -1; + } + + public StorageLayer(Storage backend, int maxVersions) { + this.backend = backend; + this.maxVersions = maxVersions; } public void protection(ProtectionEnable protectionDomainEnable, ProtectionMode protectionDomainMode, @@ -188,6 +195,7 @@ public Map> putAll(final NavigableMap dataMa Data newData = entry.getValue(); if (!securityDomainCheck(key.locationAndDomainKey(), publicKey, publicKey, domainProtection)) { retVal.put(key, PutStatus.FAILED_SECURITY); + entry.getValue().release(); continue; } @@ -205,6 +213,7 @@ public Map> putAll(final NavigableMap dataMa if (!securityEntryCheck(key.locationAndDomainAndContentKey(), publicKey, dataKey, newData.isProtectedEntry())) { retVal.put(key, PutStatus.FAILED_SECURITY); + entry.getValue().release(); continue; } @@ -212,15 +221,18 @@ public Map> putAll(final NavigableMap dataMa if (contains) { if(putIfAbsent) { retVal.put(key, PutStatus.FAILED_NOT_ABSENT); + entry.getValue().release(); continue; } final Data oldData = backend.get(key); if(oldData.isDeleted()) { retVal.put(key, PutStatus.DELETED); + entry.getValue().release(); continue; } if(!oldData.basedOnSet().equals(newData.basedOnSet())) { retVal.put(key, PutStatus.VERSION_FORK); + entry.getValue().release(); continue; } } @@ -234,21 +246,20 @@ public Map> putAll(final NavigableMap dataMa if(newData.hasPrepareFlag()) { retVal.put(key, PutStatus.OK_PREPARED); } else { - if(newData.equals(oldData)) { - retVal.put(key, PutStatus.OK_UNCHANGED); - } else { - retVal.put(key, PutStatus.OK); - } + retVal.put(key, PutStatus.OK); } - if(oldData != null) { + if(oldData != null && oldData != newData) { oldData.release(); } } - //now check for forks + for(Number480 key:keysToCheck) { + + //now check for forks Number640 minVersion = new Number640(key, Number160.ZERO); Number640 maxVersion = new Number640(key, Number160.MAX_VALUE); - NavigableMap tmp = backend.subMap(minVersion, maxVersion, -1, true); + NavigableMap tmp = backend.subMap(minVersion, maxVersion); + tmp = filterCopy(tmp, -1, true); NavigableMap heads = getLatestInternal(tmp); if(heads.size() > 1) { for(Number640 fork:heads.keySet()) { @@ -257,7 +268,23 @@ public Map> putAll(final NavigableMap dataMa } } } - } + + //now remove versions + if (maxVersions > 0) { + NavigableMap versions = backend.subMap(minVersion, maxVersion); + + while (!versions.isEmpty() + && versions.firstKey().versionKey().timestamp() + maxVersions <= versions.lastKey().versionKey() + .timestamp()) { + Map.Entry entry = versions.pollFirstEntry(); + Data removed = backend.remove(entry.getKey(), true); + if(removed != null) { + removed.release(); + } + backend.removeTimeout(entry.getKey()); + } + } + } return retVal; } finally { @@ -292,11 +319,10 @@ public Pair> remove(Number640 key, PublicKey publicKey, boolean re } backend.removeTimeout(key); Data removed = backend.remove(key, returnData); - if(removed != null && returnData) { - removed.releaseAfterSend(); - } else if(removed != null) { + if(removed != null && !returnData) { removed.release(); } + // else -> it will be removed in the encoder return new Pair>(removed, PutStatus.OK); } finally { lock.unlock(); @@ -306,7 +332,8 @@ public Pair> remove(Number640 key, PublicKey publicKey, boolean re public Data get(Number640 key) { RangeLock.Range lock = lock(key); try { - return getInternal(key); + Data tmp = getInternal(key); + return tmp == null? null:tmp.duplicate(); } finally { lock.unlock(); } @@ -324,9 +351,8 @@ private Data getInternal(Number640 key) { public NavigableMap get(Number640 from, Number640 to, int limit, boolean ascending) { RangeLock.Range lock = rangeLock.lock(from, to); try { - NavigableMap tmp = backend.subMap(from, to, limit, ascending); - removePrepared(tmp); - + NavigableMap tmp = backend.subMap(from, to); + tmp = filterCopy(tmp, limit, ascending); return tmp; } finally { lock.unlock(); @@ -336,8 +362,8 @@ public NavigableMap get(Number640 from, Number640 to, int limit public NavigableMap getLatestVersion(Number640 key) { RangeLock.Range lock = lock(key.locationAndDomainAndContentKey()); try { - NavigableMap tmp = backend.subMap(key.minVersionKey(), key.maxVersionKey(), -1, true); - removePrepared(tmp); + NavigableMap tmp = backend.subMap(key.minVersionKey(), key.maxVersionKey()); + tmp = filterCopy(tmp, -1, true); return getLatestInternal(tmp); } finally { lock.unlock(); @@ -358,33 +384,19 @@ private NavigableMap getLatestInternal(NavigableMap tmp) { - final Iterator> iterator = tmp.entrySet().iterator(); - while (iterator.hasNext()) { - final Map.Entry entry = iterator.next(); - if (entry.getValue().hasPrepareFlag()) { - iterator.remove(); + private NavigableMap filterCopy(final NavigableMap tmp, int limit, boolean ascending) { + NavigableMap retVal = new TreeMap(); + int counter = 0; + for(Map.Entry entry : tmp.entrySet()) { + if (!entry.getValue().hasPrepareFlag()) { + retVal.put(entry.getKey(), entry.getValue().duplicate()); + if(limit >= 0 && counter++ >= limit) { + break; + } } } + return ascending? retVal : retVal.descendingMap(); } - - //recursive version - @Deprecated - private void deletePredecessors2(Number640 key, NavigableMap sortedMap) { - Data version = sortedMap.remove(key); - // check if version has been already deleted - if (version == null) { - return; - } - // check if version is initial version - if (version.basedOnSet().isEmpty()) { - return; - } - // remove all predecessor versions recursively - for (Number160 basedOnKey : version.basedOnSet()) { - deletePredecessors(new Number640(key.locationAndDomainAndContentKey(), basedOnKey), sortedMap); - } - } //iterative version private void deletePredecessors(Number640 key, NavigableMap sortedMap) { @@ -394,10 +406,13 @@ private void deletePredecessors(Number640 key, NavigableMap sor while(!toRemove.isEmpty()) { //System.err.println("counter: "+ (counter++)); final Data version = sortedMap.remove(toRemove.remove(0)); - // check if version has been already deleted && // check if version is initial version - if(version != null && !version.basedOnSet().isEmpty()) { - for (final Number160 basedOnKey : version.basedOnSet()) { - toRemove.add(new Number640(key.locationAndDomainAndContentKey(), basedOnKey)); + if(version != null) { + version.release(); + // check if version has been already deleted && // check if version is initial version + if(!version.basedOnSet().isEmpty()) { + for (final Number160 basedOnKey : version.basedOnSet()) { + toRemove.add(new Number640(key.locationAndDomainAndContentKey(), basedOnKey)); + } } } } @@ -406,7 +421,7 @@ private void deletePredecessors(Number640 key, NavigableMap sor public NavigableMap get() { RangeLock.Range lock = lock(); try { - return backend.map(); + return filterCopy(backend.map(), -1, true); } finally { lock.unlock(); } @@ -426,40 +441,48 @@ public NavigableMap get(Number640 from, Number640 to, SimpleBlo int limit, boolean ascending, boolean isBloomFilterAnd) { RangeLock.Range lock = rangeLock.lock(from, to); try { - NavigableMap tmp = backend.subMap(from, to, limit, ascending); + NavigableMap tmp = backend.subMap(from, to); + tmp = filterCopy(tmp, limit, ascending); Iterator> iterator = tmp.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); if (entry.getValue().hasPrepareFlag()) { + entry.getValue().release(); iterator.remove(); continue; } if (isBloomFilterAnd) { if (!contentKeyBloomFilter.contains(entry.getKey().contentKey())) { + entry.getValue().release(); iterator.remove(); continue; } if (!versionKeyBloomFilter.contains(entry.getKey().versionKey())) { + entry.getValue().release(); iterator.remove(); continue; } if (!contentBloomFilter.contains(entry.getValue().hash())) { + entry.getValue().release(); iterator.remove(); continue; } } else { if (contentKeyBloomFilter.contains(entry.getKey().contentKey())) { + entry.getValue().release(); iterator.remove(); continue; } if (versionKeyBloomFilter.contains(entry.getKey().versionKey())) { + entry.getValue().release(); iterator.remove(); continue; } if (contentBloomFilter.contains(entry.getValue().hash())) { + entry.getValue().release(); iterator.remove(); continue; } @@ -475,7 +498,7 @@ public NavigableMap get(Number640 from, Number640 to, SimpleBlo public NavigableMap removeReturnData(Number640 from, Number640 to, PublicKey publicKey) { RangeLock.Range lock = rangeLock.lock(from, to); try { - Map tmp = backend.subMap(from, to, -1, true); + Map tmp = backend.subMap(from, to); NavigableMap result = new TreeMap(); for (Number640 key : tmp.keySet()) { @@ -490,7 +513,6 @@ public NavigableMap removeReturnData(Number640 from, Number640 if (toRemove!= null && (toRemove.publicKey() == null || toRemove.publicKey().equals(publicKey))) { backend.removeTimeout(key); Data removed = backend.remove(key, true); - removed.releaseAfterSend(); result.put(key, removed); } } @@ -504,7 +526,7 @@ public NavigableMap removeReturnData(Number640 from, Number640 public SortedMap removeReturnStatus(Number640 from, Number640 to, PublicKey publicKey) { RangeLock.Range lock = rangeLock.lock(from, to); try { - Map tmp = backend.subMap(from, to, -1, true); + Map tmp = backend.subMap(from, to); SortedMap result = new TreeMap(); for (Number640 key : tmp.keySet()) { Pair> pair = remove(key, publicKey, false); @@ -550,7 +572,7 @@ public void checkTimeout() { private boolean isEmpty(Number160 locationKey) { Number640 from = new Number640(locationKey, Number160.ZERO, Number160.ZERO, Number160.ZERO); Number640 to = new Number640(locationKey, Number160.MAX_VALUE, Number160.MAX_VALUE, Number160.MAX_VALUE); - Map tmp = backend.subMap(from, to, 1, false); + Map tmp = backend.subMap(from, to); return tmp.size() == 0; } @@ -562,7 +584,8 @@ public DigestInfo digest(Number640 from, Number640 to, int limit, boolean ascend DigestInfo digestInfo = new DigestInfo(); RangeLock.Range lock = rangeLock.lock(from, to); try { - Map tmp = backend.subMap(from, to, limit, ascending); + NavigableMap tmp = backend.subMap(from, to); + tmp = filterCopy(tmp, limit, ascending); for (Map.Entry entry : tmp.entrySet()) { if (!entry.getValue().hasPrepareFlag()) { digestInfo.put(entry.getKey(), entry.getValue().basedOnSet()); @@ -585,7 +608,8 @@ public DigestInfo digest(Number320 locationAndDomainKey, SimpleBloomFilter tmp = backend.subMap(from, to, limit, ascending); + NavigableMap tmp = backend.subMap(from, to); + tmp = filterCopy(tmp, limit, ascending); for (Map.Entry entry : tmp.entrySet()) { if (isBloomFilterAnd) { if (keyBloomFilter == null || keyBloomFilter.contains(entry.getKey().contentKey())) { @@ -881,7 +905,7 @@ public Enum putConfirm(PublicKey publicKey, Number640 key, Data newData) { long expiration = data.expirationMillis(); // handle timeout backend.addTimeout(key, expiration); - Data oldData = backend.put(key, data); + backend.put(key, data); //don't release data as we just update return PutStatus.OK; } else { diff --git a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java index 5a56c65e2..451e58284 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java @@ -21,12 +21,10 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.NavigableMap; import java.util.Set; import java.util.SortedMap; -import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; @@ -42,7 +40,6 @@ public class StorageMemory implements Storage { public static final int DEFAULT_STORAGE_CHECK_INTERVAL= 60 * 1000; - public static final int DEFAULT_MAX_VERSIONS= -1; private static final Logger LOG = LoggerFactory.getLogger(StorageMemory.class); @@ -63,42 +60,20 @@ public class StorageMemory implements Storage { final private Map> responsibilityMapRev = new ConcurrentHashMap>(); final int storageCheckIntervalMillis; - final int maxVersions; - public StorageMemory() { - this(DEFAULT_STORAGE_CHECK_INTERVAL, DEFAULT_MAX_VERSIONS); - } - public StorageMemory(int storageCheckIntervalMillis) { - this(storageCheckIntervalMillis, DEFAULT_MAX_VERSIONS); + public StorageMemory() { + this(DEFAULT_STORAGE_CHECK_INTERVAL); } - public StorageMemory(int storageCheckIntervalMillis, int maxVersions) { + public StorageMemory(int storageCheckIntervalMillis) { this.storageCheckIntervalMillis = storageCheckIntervalMillis; - this.maxVersions = maxVersions; } // Core @Override public Data put(Number640 key, Data value) { - final Data oldData = dataMap.put(key, value); - if (maxVersions > 0) { - NavigableMap versions = dataMap.subMap( - new Number640(key.locationKey(), key.domainKey(), key.contentKey(), Number160.ZERO), true, - new Number640(key.locationKey(), key.domainKey(), key.contentKey(), Number160.MAX_VALUE), true); - - while (!versions.isEmpty() - && versions.firstKey().versionKey().timestamp() + maxVersions <= versions.lastKey().versionKey() - .timestamp()) { - Map.Entry entry = versions.pollFirstEntry(); - Data removed = remove(entry.getKey(), false); - if(removed != null) { - removed.release(); - } - removeTimeout(entry.getKey()); - } - } - return oldData; + return dataMap.put(key, value); } @Override @@ -124,107 +99,20 @@ public Data remove(Number640 key, boolean returnData) { @Override public NavigableMap remove(Number640 fromKey, Number640 toKey) { - NavigableMap tmp = dataMap.subMap(fromKey, true, toKey, true); - - // new TreeMap(tmp); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. - - final NavigableMap retVal = new ConcurrentSkipListMap(tmp); + ConcurrentSkipListMap tmp = (ConcurrentSkipListMap) dataMap.subMap(fromKey, true, toKey, true); + final NavigableMap retVal = tmp.clone(); tmp.clear(); return retVal; } @Override - public NavigableMap subMap(Number640 fromKey, Number640 toKey, int limit, - boolean ascending) { - - final NavigableMap clone = ((ConcurrentSkipListMap)dataMap).clone(); - final NavigableMap tmp = clone.subMap(fromKey, true, toKey, true); - final NavigableMap retVal = new TreeMap(); - if (limit < 0) { - - // new TreeMap(tmp); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. - //for(Map.Entry entry:(ascending ? tmp : tmp.descendingMap()).entrySet()) { - // retVal.put(entry.getKey(), entry.getValue()); - //} - return ascending ? tmp : tmp.descendingMap(); - } else { - Iterator> iterator = ascending ? tmp.entrySet().iterator() : tmp - .descendingMap().entrySet().iterator(); - for (int i = 0; iterator.hasNext() && i < limit; i++) { - Map.Entry entry = iterator.next(); - retVal.put(entry.getKey(), entry.getValue()); - } - } - return retVal; + public NavigableMap subMap(Number640 fromKey, Number640 toKey) { + return dataMap.subMap(fromKey, true, toKey, true); } @Override - public NavigableMap map() { - - // new TreeMap(tmp); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. - final NavigableMap retVal = new TreeMap(); - for(final Map.Entry entry:dataMap.entrySet()) { - retVal.put(entry.getKey(), entry.getValue()); - } - - return retVal; + public NavigableMap map() { + return dataMap; } // Maintenance @@ -239,6 +127,12 @@ public void addTimeout(Number640 key, long expiration) { } removeRevTimeout(key, oldExpiration); } + + //TODO: unnecessary creation of object + private Set putIfAbsent2(long expiration, Set hashSet) { + Set timeouts = timeoutMapRev.putIfAbsent(expiration, hashSet); + return timeouts == null ? hashSet : timeouts; + } @Override public void removeTimeout(Number640 key) { @@ -288,10 +182,7 @@ public boolean isDomainProtectedByOthers(Number320 key, PublicKey publicKey) { return retVal; } - private Set putIfAbsent2(long expiration, Set hashSet) { - Set timeouts = timeoutMapRev.putIfAbsent(expiration, hashSet); - return timeouts == null ? hashSet : timeouts; - } + @Override public Number160 findPeerIDsForResponsibleContent(Number160 locationKey) { diff --git a/dht/src/main/java/net/tomp2p/dht/UtilsDHT.java b/dht/src/main/java/net/tomp2p/dht/UtilsDHT.java index b18c7abac..1017b908f 100644 --- a/dht/src/main/java/net/tomp2p/dht/UtilsDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/UtilsDHT.java @@ -5,18 +5,7 @@ import net.tomp2p.futures.FutureDone; public class UtilsDHT { - public static int dataSize(PutBuilder putBuilder) { - if(putBuilder.isPutMeta() && putBuilder.changePublicKey()!=null) { - //we only send a marker - return 1; - } else if (putBuilder.isPutConfirm()) { - return 1; - } else if(putBuilder.dataMap()!=null) { - return putBuilder.dataMap().size(); - } else { - return putBuilder.dataMapContent().size(); - } - } + public static int dataSize(RemoveBuilder builder) { if (builder.contentKeys()!=null) { diff --git a/dht/src/main/java/net/tomp2p/dht/VotingSchemeDHT.java b/dht/src/main/java/net/tomp2p/dht/VotingSchemeDHT.java index 7159c2803..a210bb348 100644 --- a/dht/src/main/java/net/tomp2p/dht/VotingSchemeDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/VotingSchemeDHT.java @@ -15,8 +15,6 @@ */ package net.tomp2p.dht; -import io.netty.buffer.ByteBuf; - import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -30,6 +28,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.DigestResult; import net.tomp2p.storage.Data; +import net.tomp2p.storage.DataBuffer; public class VotingSchemeDHT implements EvaluatingSchemeDHT { @@ -126,7 +125,7 @@ public Object evaluate3(Map rawKeys) { } @Override - public ByteBuf evaluate4(Map rawKeys) { + public DataBuffer evaluate4(Map rawKeys) { return evaluate0(rawKeys); } diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 0e9806df6..4833b62ed 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -54,6 +54,7 @@ import net.tomp2p.rpc.ObjectDataReply; import net.tomp2p.rpc.RawDataReply; import net.tomp2p.storage.Data; +import net.tomp2p.storage.DataBuffer; import net.tomp2p.utils.Utils; import org.junit.Assert; @@ -379,6 +380,40 @@ public void testPutGet() throws Exception { } } } + + @Test + public void testPutGetRelease() throws Exception { + PeerDHT master = null; + try { + // setup + PeerDHT[] peers = UtilsDHT2.createNodes(2000, rnd, 4001); + master = peers[0]; + UtilsDHT2.perfectRouting(peers); + // do testing + RoutingConfiguration rc = new RoutingConfiguration(2, 10, 2); + RequestP2PConfiguration pc = new RequestP2PConfiguration(3, 5, 0); + Data data = new Data(new byte[44444]); + FuturePut fput = peers[444].put(peers[30].peerID()).data(new Number160(5), data) + .domainKey(Number160.createHash("test")).routingConfiguration(rc) + .requestP2PConfiguration(pc).start(); + fput.awaitUninterruptibly(); + fput.futureRequests().awaitUninterruptibly(); + Assert.assertEquals(true, fput.isSuccess()); + rc = new RoutingConfiguration(0, 0, 10, 1); + pc = new RequestP2PConfiguration(1, 0, 0); + + FutureGet fget = peers[555].get(peers[30].peerID()).domainKey(Number160.createHash("test")) + .contentKey(new Number160(5)).routingConfiguration(rc).requestP2PConfiguration(pc).start(); + fget.awaitUninterruptibly(); + Assert.assertEquals(true, fget.isSuccess()); + Assert.assertEquals(true, fget.rawData().values().iterator().next().values().iterator().next().isHeapBuffer()); + Assert.assertEquals(true, fget.requests().get(0).responseMessage().dataMap(0).dataMap().values().iterator().next().isHeapBuffer()); + } finally { + if (master != null) { + master.shutdown().await(); + } + } + } @Test public void testPutConvert() throws Exception { @@ -919,7 +954,7 @@ public void testData() throws Exception { // do testing ByteBuf c = Unpooled.buffer(); c.writeInt(77); - Buffer b = new Buffer(c); + DataBuffer d = new DataBuffer(c); peers[50].peer().rawDataReply(new RawDataReply() { @Override public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean complete) { @@ -930,7 +965,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean complete) return ret; } }); - FutureDirect fd = master.peer().sendDirect(peers[50].peerAddress()).buffer(b).start(); + FutureDirect fd = master.peer().sendDirect(peers[50].peerAddress()).dataBuffer(d).start(); fd.await(); if (fd.buffer() == null) { System.out.println("damm"); @@ -959,7 +994,7 @@ public void testData2() throws Exception { // do testing ByteBuf c = Unpooled.buffer(); c.writeInt(77); - Buffer b = new Buffer(c); + DataBuffer d = new DataBuffer(c); peers[50].peer().rawDataReply(new RawDataReply() { @Override public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean complete) { @@ -967,7 +1002,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean complete) return requestBuffer; } }); - FutureDirect fd = master.peer().sendDirect(peers[50].peerAddress()).buffer(b).start(); + FutureDirect fd = master.peer().sendDirect(peers[50].peerAddress()).dataBuffer(d).start(); fd.await(); System.out.println("done1"); Assert.assertEquals(true, fd.isSuccess()); @@ -1440,7 +1475,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro for (int i = 0; i < 125; i++) { final byte[] b = new byte[10000]; FuturePeerConnection pc = master.createPeerConnection(slave.peerAddress()); - list1.add(master.sendDirect(pc).buffer(new Buffer(Unpooled.wrappedBuffer(b))).start()); + list1.add(master.sendDirect(pc).dataBuffer(new DataBuffer(Unpooled.wrappedBuffer(b))).start()); list3.add(pc); // pc.close(); } @@ -1449,7 +1484,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro final byte[] b = new byte[10000]; byte[] me = Utils.intToByteArray(i); System.arraycopy(me, 0, b, 0, 4); - list2.add(master.sendDirect(slave.peerAddress()).buffer(new Buffer(Unpooled.wrappedBuffer(b))) + list2.add(master.sendDirect(slave.peerAddress()).dataBuffer(new DataBuffer(Unpooled.wrappedBuffer(b))) .start()); } for (BaseFuture bf : list1) { @@ -2239,8 +2274,8 @@ private void send2(final PeerDHT p1, final PeerDHT p2, final ByteBuf toStore1, f if (count == 0) { return; } - Buffer b = new Buffer(toStore1); - FutureDirect fd = p1.peer().sendDirect(p2.peerAddress()).buffer(b).start(); + DataBuffer b = new DataBuffer(toStore1); + FutureDirect fd = p1.peer().sendDirect(p2.peerAddress()).dataBuffer(b).start(); fd.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureDirect future) throws Exception { diff --git a/dht/src/test/java/net/tomp2p/dht/TestH2H.java b/dht/src/test/java/net/tomp2p/dht/TestH2H.java index e368b25ae..4b1711c38 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestH2H.java +++ b/dht/src/test/java/net/tomp2p/dht/TestH2H.java @@ -514,10 +514,10 @@ public void testMaxVersionLimit() throws IOException, ClassNotFoundException, No // create peers which accept only two versions KeyPair keyPairPeer1 = gen.generateKeyPair(); p1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(1)).ports(5000).keyPair(keyPairPeer1).start()) - .storage(new StorageMemory(1000, 2)).start(); + .storageLayer(new StorageLayer(new StorageMemory(1000), 2)).start(); KeyPair keyPairPeer2 = gen.generateKeyPair(); p2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(2)).masterPeer(p1.peer()) - .keyPair(keyPairPeer2).start()).storage(new StorageMemory(1000, 2)).start(); + .keyPair(keyPairPeer2).start()).storageLayer(new StorageLayer(new StorageMemory(1000), 2)).start(); p2.peer().bootstrap().peerAddress(p1.peerAddress()).start().awaitUninterruptibly(); p1.peer().bootstrap().peerAddress(p2.peerAddress()).start().awaitUninterruptibly(); KeyPair keyPair1 = gen.generateKeyPair(); diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index dac6b4924..ee0608bd3 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -166,7 +166,7 @@ public void testAdd() throws Exception { // Set tofetch = new HashSet(); Number640 from = new Number640(key, Number160.ZERO, Number160.ZERO); Number640 to = new Number640(key, Number160.MAX_VALUE, Number160.MAX_VALUE); - SortedMap c = storeRecv.subMap(from, to, -1, true); + SortedMap c = storeRecv.subMap(from, to); Assert.assertEquals(1, c.size()); for (Data data : c.values()) { Assert.assertEquals((Integer) 1, (Integer) data.object()); @@ -186,7 +186,7 @@ public void testAdd() throws Exception { // Set tofetch = new HashSet(); from = new Number640(key, Number160.ZERO, Number160.ZERO); to = new Number640(key, Number160.MAX_VALUE, Number160.MAX_VALUE); - c = storeRecv.subMap(from, to, -1, true); + c = storeRecv.subMap(from, to); Assert.assertEquals(2, c.size()); for (Data data : c.values()) { Assert.assertEquals((Integer) 1, (Integer) data.object()); @@ -260,7 +260,7 @@ public void testStorePut() throws Exception { fr.awaitUninterruptibly(); System.err.println(fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); - Map result2 = storeRecv.subMap(key1.minContentKey(), key1.maxContentKey(), -1, true); + Map result2 = storeRecv.subMap(key1.minContentKey(), key1.maxContentKey()); Assert.assertEquals(result2.size(), 2); //Number480 search = new Number480(key, new Number160(88)); Number640 key2 = new Number640(new Number160(33), Number160.createHash("test"), new Number160(88), Number160.ZERO); diff --git a/storage/src/main/java/net/tomp2p/storage/StorageDisk.java b/storage/src/main/java/net/tomp2p/storage/StorageDisk.java index 1106e7386..137c7b4f2 100644 --- a/storage/src/main/java/net/tomp2p/storage/StorageDisk.java +++ b/storage/src/main/java/net/tomp2p/storage/StorageDisk.java @@ -22,7 +22,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.NavigableMap; import java.util.Set; @@ -111,27 +110,6 @@ public Data remove(Number640 key, boolean returnData) { @Override public NavigableMap remove(Number640 from, Number640 to) { NavigableMap tmp = dataMap.subMap(from, true, to, true); - - // new TreeMap(tmp); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. final NavigableMap retVal = new TreeMap(); for(final Map.Entry entry:tmp.entrySet()) { retVal.put(entry.getKey(), entry.getValue()); @@ -143,76 +121,13 @@ public NavigableMap remove(Number640 from, Number640 to) { } @Override - public NavigableMap subMap(Number640 from, Number640 to, int limit, boolean ascending) { - NavigableMap tmp = dataMap.subMap(from, true, to, true); - final NavigableMap retVal = new TreeMap(); - if (limit < 0) { - - // new TreeMap(tmp); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. - - for(final Map.Entry entry:(ascending ? tmp : tmp.descendingMap()).entrySet()) { - retVal.put(entry.getKey(), entry.getValue()); - } - } else { - limit = Math.min(limit, tmp.size()); - Iterator> iterator = ascending ? tmp.entrySet().iterator() : tmp - .descendingMap().entrySet().iterator(); - for (int i = 0; iterator.hasNext() && i < limit; i++) { - Map.Entry entry = iterator.next(); - retVal.put(entry.getKey(), entry.getValue()); - } - } - return retVal; + public NavigableMap subMap(Number640 from, Number640 to) { + return dataMap.subMap(from, true, to, true); } @Override - public NavigableMap map() { - - // new TreeMap(dataMap); is not possible as this may lead to no such element exception: - // - // java.util.NoSuchElementException: null - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapIter.advance(ConcurrentSkipListMap.java:3030) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3100) ~[na:1.7.0_60] - // at java.util.concurrent.ConcurrentSkipListMap$SubMap$SubMapEntryIterator.next(ConcurrentSkipListMap.java:3096) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2394) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2418) ~[na:1.7.0_60] - // at java.util.TreeMap.buildFromSorted(TreeMap.java:2344) ~[na:1.7.0_60] - // at java.util.TreeMap.(TreeMap.java:195) ~[na:1.7.0_60] - // at net.tomp2p.dht.StorageMemory.subMap(StorageMemory.java:119) ~[classes/:na] - // - // the reason is that the size in TreeMap.buildFromSorted is stored beforehand, then iteratated. If the size changes, - // then you will call next() that returns null and an exception is thrown. - final NavigableMap retVal = new TreeMap(); - for(final Map.Entry entry:dataMap.entrySet()) { - retVal.put(entry.getKey(), entry.getValue()); - } - - return retVal; + public NavigableMap map() { + return dataMap; } // Maintenance From 0cd3e3faedb5d40568d9fb8335681ffa365d326c Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 4 Jun 2015 16:05:24 +0200 Subject: [PATCH 004/135] fixed #106 --- .../main/java/net/tomp2p/dht/AddBuilder.java | 3 +- .../java/net/tomp2p/dht/DigestBuilder.java | 5 +- .../net/tomp2p/dht/DistributedHashTable.java | 95 +++++++------------ .../main/java/net/tomp2p/dht/GetBuilder.java | 5 +- .../java/net/tomp2p/dht/RemoveBuilder.java | 18 +++- .../main/java/net/tomp2p/dht/SendBuilder.java | 4 +- 6 files changed, 65 insertions(+), 65 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/AddBuilder.java b/dht/src/main/java/net/tomp2p/dht/AddBuilder.java index df3274701..f0d112643 100644 --- a/dht/src/main/java/net/tomp2p/dht/AddBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/AddBuilder.java @@ -104,6 +104,7 @@ public FuturePut start() { rnd = new Random(); } - return peer.distributedHashTable().add(this); + final FuturePut futureDHT = new FuturePut(this, requestP2PConfiguration().minimumResults(), dataSet().size()); + return peer.distributedHashTable().add(this, futureDHT); } } diff --git a/dht/src/main/java/net/tomp2p/dht/DigestBuilder.java b/dht/src/main/java/net/tomp2p/dht/DigestBuilder.java index fda2d1ac4..b74d7d042 100644 --- a/dht/src/main/java/net/tomp2p/dht/DigestBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/DigestBuilder.java @@ -294,6 +294,9 @@ public FutureDigest start() { if (evaluationScheme == null) { evaluationScheme = new VotingSchemeDHT(); } - return peer.distributedHashTable().digest(this); + + final FutureDigest futureDigest = new FutureDigest(this, requestP2PConfiguration() + .minimumResults(), evaluationScheme); + return peer.distributedHashTable().digest(this, futureDigest); } } diff --git a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java index e9d7a7bf7..68a4e29a4 100644 --- a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java +++ b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java @@ -75,9 +75,7 @@ public DistributedHashTable(DistributedRouting routing, StorageRPC storeRCP, Dir this.directDataRPC = directDataRPC; } - public FuturePut add(final AddBuilder builder) { - final FuturePut futureDHT = new FuturePut(builder, builder.requestP2PConfiguration() - .minimumResults(), builder.dataSet().size()); + public FuturePut add(final AddBuilder builder, final FuturePut futurePut) { builder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FutureChannelCreator future) throws Exception { @@ -85,7 +83,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio final RoutingBuilder routingBuilder = createBuilder(builder); final FutureRouting futureRouting = routing.route(routingBuilder, Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futurePut.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FutureRouting futureRouting) throws Exception { @@ -93,7 +91,7 @@ public void operationComplete(final FutureRouting futureRouting) throws Exceptio logger.debug("adding lkey={} on {}", builder.locationKey(), futureRouting.potentialHits()); parallelRequests(builder.requestP2PConfiguration(), - EMPTY_NAVIGABLE_SET , futureRouting.potentialHits(), futureDHT, false, + EMPTY_NAVIGABLE_SET , futureRouting.potentialHits(), futurePut, false, future.channelCreator(), new OperationMapper() { Map> rawData = new HashMap>(); @@ -119,30 +117,20 @@ public void interMediateResponse(FutureResponse future) { } }); } else { - futureDHT.failed(futureRouting); + futurePut.failed(futureRouting); } } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futurePut.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futurePut.failed(future); } } }); - return futureDHT; + return futurePut; } - /* - * public FutureDHT direct(final Number160 locationKey, final ByteBuf buffer, final boolean raw, final - * RoutingConfiguration routingConfiguration, final RequestP2PConfiguration p2pConfiguration, final - * FutureCreate futureCreate, final boolean cancelOnFinish, final boolean manualCleanup, final - * FutureChannelCreator futureChannelCreator, final ConnectionReservation connectionReservation) { - */ - - public FutureSend direct(final SendBuilder builder) { - - final FutureSend futureDHT = new FutureSend(builder, builder.requestP2PConfiguration() - .minimumResults(), new VotingSchemeDHT()); + public FutureSend direct(final SendBuilder builder, final FutureSend futureSend) { builder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override @@ -152,7 +140,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio final RoutingBuilder routingBuilder = createBuilder(builder); final FutureRouting futureRouting = routing.route(routingBuilder, Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futureSend.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureRouting futureRouting) throws Exception { @@ -160,7 +148,7 @@ public void operationComplete(FutureRouting futureRouting) throws Exception { logger.debug("storing lkey={} on {}", builder.locationKey(), futureRouting.potentialHits()); parallelRequests(builder.requestP2PConfiguration(), - EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), futureDHT, + EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), futureSend, builder.isCancelOnFinish(), future.channelCreator(), new OperationMapper() { Map rawChannels = new HashMap(); @@ -207,19 +195,19 @@ public void interMediateResponse(FutureResponse future) { } }); } else { - futureDHT.failed(futureRouting); + futureSend.failed(futureRouting); } } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futureSend.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futureSend.failed(future); } } }); - return futureDHT; + return futureSend; } public FuturePut put(final PutBuilder putBuilder, final FuturePut futurePut) { @@ -299,10 +287,7 @@ public void interMediateResponse(final FutureResponse future) { return futurePut; } - public FutureGet get(final GetBuilder builder) { - - final FutureGet futureDHT = new FutureGet(builder, builder.requestP2PConfiguration() - .minimumResults(), new VotingSchemeDHT()); + public FutureGet get(final GetBuilder builder, final FutureGet futureGet) { builder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override @@ -313,7 +298,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio fillRoutingBuilder(builder, routingBuilder); final FutureRouting futureRouting = routing.route(routingBuilder, builder.isFastGet()? Type.REQUEST_2 : Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futureGet.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureRouting futureRouting) throws Exception { @@ -328,7 +313,7 @@ public void operationComplete(FutureRouting futureRouting) throws Exception { p2pConfiguration2, builder.isFastGet() ? futureRouting.directHits(): EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), - futureDHT, true, + futureGet, true, future.channelCreator(), new OperationMapper() { Map> rawData = new HashMap>(); Map rawDigest = new HashMap(); @@ -391,22 +376,20 @@ public void interMediateResponse(FutureResponse future) { } }); } else { - futureDHT.failed(futureRouting); + futureGet.failed(futureRouting); } } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futureGet.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futureGet.failed(future); } } }); - return futureDHT; + return futureGet; } - public FutureDigest digest(final DigestBuilder builder) { - final FutureDigest futureDHT = new FutureDigest(builder, builder.requestP2PConfiguration() - .minimumResults(), new VotingSchemeDHT()); + public FutureDigest digest(final DigestBuilder builder, final FutureDigest futureDigest) { builder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override @@ -417,7 +400,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio fillRoutingBuilder(builder, routingBuilder); final FutureRouting futureRouting = routing.route(routingBuilder, builder.isFastGet()? Type.REQUEST_2 : Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futureDigest.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureRouting futureRouting) throws Exception { @@ -429,7 +412,7 @@ public void operationComplete(FutureRouting futureRouting) throws Exception { builder.requestP2PConfiguration(), builder.isFastGet() ? futureRouting.directHits(): EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), - futureDHT, true, + futureDigest, true, future.channelCreator(), new OperationMapper() { Map rawDigest = new HashMap(); @@ -473,28 +456,20 @@ public void interMediateResponse(FutureResponse future) { } }); } else { - futureDHT.failed(futureRouting); + futureDigest.failed(futureRouting); } } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futureDigest.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futureDigest.failed(future); } } }); - return futureDHT; + return futureDigest; } - /* - * public FutureDHT remove(final Number160 locationKey, final Number160 domainKey, final Collection - * contentKeys, final RoutingConfiguration routingConfiguration, final RequestP2PConfiguration p2pConfiguration, - * final boolean returnResults, final boolean signMessage, final boolean isManualCleanup, FutureCreate - * futureCreate, final FutureChannelCreator futureChannelCreator, final ConnectionReservation connectionReservation) - * { - */ - public FutureRemove remove(final RemoveBuilder builder) { - final FutureRemove futureDHT = new FutureRemove(builder, new VotingSchemeDHT()); + public FutureRemove remove(final RemoveBuilder builder, final FutureRemove futureRemove) { builder.futureChannelCreator().addListener(new BaseFutureAdapter() { @Override @@ -505,7 +480,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio fillRoutingBuilder(builder, routingBuilder); final FutureRouting futureRouting = routing.route(routingBuilder, builder.isFastGet() ? Type.REQUEST_2 : Type.REQUEST_1, future.channelCreator()); - futureDHT.futureRouting(futureRouting); + futureRemove.futureRouting(futureRouting); futureRouting.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureRouting futureRouting) throws Exception { @@ -520,7 +495,7 @@ public void operationComplete(FutureRouting futureRouting) throws Exception { parallelRequests(p2pConfiguration2, builder.isFastGet() ? futureRouting.directHits(): EMPTY_NAVIGABLE_SET, futureRouting.potentialHits(), - futureDHT, false, future.channelCreator(), + futureRemove, false, future.channelCreator(), new OperationMapper() { Map> rawDataResult = new HashMap>(); @@ -558,19 +533,19 @@ public void interMediateResponse(FutureResponse future) { } }); } else - futureDHT.failed(futureRouting); + futureRemove.failed(futureRouting); } }); - futureDHT.addFutureDHTReleaseListener(future.channelCreator()); + futureRemove.addFutureDHTReleaseListener(future.channelCreator()); } else { - futureDHT.failed(future); + futureRemove.failed(future); } } }); - return futureDHT; + return futureRemove; } /** diff --git a/dht/src/main/java/net/tomp2p/dht/GetBuilder.java b/dht/src/main/java/net/tomp2p/dht/GetBuilder.java index dd64ba47e..0a3d312c8 100644 --- a/dht/src/main/java/net/tomp2p/dht/GetBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/GetBuilder.java @@ -319,6 +319,9 @@ public FutureGet start() { contentKey = Number160.ZERO; } } - return peer.distributedHashTable().get(this); + + final FutureGet futureGet = new FutureGet(this, requestP2PConfiguration() + .minimumResults(), evaluationScheme); + return peer.distributedHashTable().get(this, futureGet); } } diff --git a/dht/src/main/java/net/tomp2p/dht/RemoveBuilder.java b/dht/src/main/java/net/tomp2p/dht/RemoveBuilder.java index d3845e51f..91ddebe4b 100644 --- a/dht/src/main/java/net/tomp2p/dht/RemoveBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/RemoveBuilder.java @@ -44,6 +44,8 @@ public class RemoveBuilder extends DHTBuilder implements Searchab private boolean fastGet = true; private boolean failIfNotFound = false; + + private EvaluatingSchemeDHT evaluationScheme; public RemoveBuilder(PeerDHT peer, Number160 locationKey) { super(peer, locationKey); @@ -158,6 +160,15 @@ public RemoveBuilder failIfNotFound() { this.failIfNotFound = true; return this; } + + public EvaluatingSchemeDHT evaluationScheme() { + return evaluationScheme; + } + + public RemoveBuilder evaluationScheme(EvaluatingSchemeDHT evaluationScheme) { + this.evaluationScheme = evaluationScheme; + return this; + } public FutureRemove start() { if (peer.peer().isShutdown()) { @@ -173,7 +184,12 @@ public FutureRemove start() { } contentKeys.add(contentKey); } + + if (evaluationScheme == null) { + evaluationScheme = new VotingSchemeDHT(); + } - return peer.distributedHashTable().remove(this); + final FutureRemove futureRemove = new FutureRemove(this, evaluationScheme); + return peer.distributedHashTable().remove(this, futureRemove); } } diff --git a/dht/src/main/java/net/tomp2p/dht/SendBuilder.java b/dht/src/main/java/net/tomp2p/dht/SendBuilder.java index a76958cb2..5b0b0e733 100644 --- a/dht/src/main/java/net/tomp2p/dht/SendBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/SendBuilder.java @@ -94,6 +94,8 @@ public FutureSend start() { return FUTURE_SHUTDOWN; } preBuild("send-builder"); - return peer.distributedHashTable().direct(this); + + final FutureSend futureSend = new FutureSend(this, requestP2PConfiguration().minimumResults(), new VotingSchemeDHT()); + return peer.distributedHashTable().direct(this, futureSend); } } From 2e5a7f4391eb8492a20375eeb4480933ea411c67 Mon Sep 17 00:00:00 2001 From: tbocek Date: Thu, 4 Jun 2015 22:14:55 +0200 Subject: [PATCH 005/135] equals is required for unit tests --- .../main/java/net/tomp2p/message/Buffer.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/src/main/java/net/tomp2p/message/Buffer.java b/core/src/main/java/net/tomp2p/message/Buffer.java index 6afcc10a0..4f68963ca 100644 --- a/core/src/main/java/net/tomp2p/message/Buffer.java +++ b/core/src/main/java/net/tomp2p/message/Buffer.java @@ -54,4 +54,24 @@ public void reset() { read = 0; buffer.resetReaderIndex(); } + + @Override + public int hashCode() { + return buffer.duplicate().readerIndex(0).hashCode() ^ length; + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof Buffer)) { + return false; + } + if (obj == this) { + return true; + } + final Buffer b = (Buffer) obj; + if(b.length != length) { + return false; + } + return b.buffer.duplicate().readerIndex(0).equals(buffer.duplicate().readerIndex(0)); + } } From 9cf262dce1996b04a5ea620ce12572116591db1c Mon Sep 17 00:00:00 2001 From: tbocek Date: Thu, 4 Jun 2015 22:35:35 +0200 Subject: [PATCH 006/135] fixed testcase, need to use copy of data --- dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index ee0608bd3..e39429eb7 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -313,9 +313,10 @@ public void testStorePutIfAbsent() throws Exception { fr.awaitUninterruptibly(); Assert.assertEquals(true, fr.isSuccess()); Number640 key = new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO); - Data c = storeRecv.get(key); + Data c = storeRecv.get(key).duplicate(); Assert.assertEquals(c, test); + c.release(); // tmp.clear(); byte[] me3 = new byte[] { 5, 6, 7 }; From 2315dfb76dda2ef1e94def5c06b57fbe24682aef Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 11:17:11 +0200 Subject: [PATCH 007/135] fixed filter copy --- dht/src/main/java/net/tomp2p/dht/StorageLayer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index af9c33787..5b2d65cdd 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -387,15 +387,15 @@ private NavigableMap getLatestInternal(NavigableMap filterCopy(final NavigableMap tmp, int limit, boolean ascending) { NavigableMap retVal = new TreeMap(); int counter = 0; - for(Map.Entry entry : tmp.entrySet()) { + for(Map.Entry entry : ascending ? tmp.entrySet() : tmp.descendingMap().entrySet()) { if (!entry.getValue().hasPrepareFlag()) { - retVal.put(entry.getKey(), entry.getValue().duplicate()); if(limit >= 0 && counter++ >= limit) { break; } + retVal.put(entry.getKey(), entry.getValue().duplicate()); } } - return ascending? retVal : retVal.descendingMap(); + return retVal; } //iterative version From 427ec6c62f0b7a2099060e3959e785223ae3b644 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 11:55:59 +0200 Subject: [PATCH 008/135] only clear buffer if we have released all buffers --- .../java/net/tomp2p/storage/DataBuffer.java | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 060aeb2dd..457ef9e3a 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -8,6 +8,8 @@ import java.util.Arrays; import java.util.List; +import net.tomp2p.utils.Utils; + public class DataBuffer { private final Object lock = new Object(); @@ -219,8 +221,15 @@ public int transferFrom(final ByteBuf buf, final int max) { @Override public int hashCode() { - //convert to heap buffer - return Arrays.hashCode(bytes()); + if(isHeapBuffer()) { + return Arrays.hashCode(heapBuffer); + } else { + int hash = 42; + for(ByteBuf buf:buffers) { + hash ^= buf.hashCode(); + } + return hash; + } } @Override @@ -232,8 +241,13 @@ public boolean equals(final Object obj) { return true; } final DataBuffer m = (DataBuffer) obj; - //convert to heap buffer - return Arrays.equals(m.bytes(), bytes()); + if(isHeapBuffer() && m.isHeapBuffer()) { + return Arrays.equals(m.bytes(), bytes()); + } else if(!isHeapBuffer() && !m.isHeapBuffer()) { + return Utils.isSameSets(buffers, m.buffers); + } else { + throw new RuntimeException("cannot compare head with direct"); + } } /*@Override @@ -272,10 +286,15 @@ public DataBuffer release() { } private DataBuffer releaseIntern() { + boolean allReleased = true; for (ByteBuf buf : buffers) { - buf.release(); + if(!buf.release() && allReleased) { + allReleased = false; + } + } + if(allReleased) { + buffers.clear(); } - buffers.clear(); return this; } From fe97a3a16674bcc17a3c25ea0d0e2abeeedf2626 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 12:16:55 +0200 Subject: [PATCH 009/135] fixed equals --- core/src/main/java/net/tomp2p/storage/DataBuffer.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 457ef9e3a..185f57c9e 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -1,6 +1,7 @@ package net.tomp2p.storage; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; import java.nio.ByteBuffer; @@ -8,8 +9,6 @@ import java.util.Arrays; import java.util.List; -import net.tomp2p.utils.Utils; - public class DataBuffer { private final Object lock = new Object(); @@ -244,7 +243,7 @@ public boolean equals(final Object obj) { if(isHeapBuffer() && m.isHeapBuffer()) { return Arrays.equals(m.bytes(), bytes()); } else if(!isHeapBuffer() && !m.isHeapBuffer()) { - return Utils.isSameSets(buffers, m.buffers); + return ByteBufUtil.equals(toByteBuf(), m.toByteBuf()); } else { throw new RuntimeException("cannot compare head with direct"); } From 996c7f6c7aace4c1235e922e87c80d6c1680efbe Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 16:26:37 +0200 Subject: [PATCH 010/135] send to self needs to duplicate the databuffer list, as otherwise, the data will disappear --- core/src/main/java/net/tomp2p/connection/Sender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 93adfc727..c612f7eae 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -423,7 +423,7 @@ public Data filter(Data data, boolean isConvertMeta, boolean isReply) { } // set new valid from as this data item might have an old one data.validFromMillis(System.currentTimeMillis()); - return data; + return data.duplicate(); } }); From c3e58ec46afdc888bb0e964e91297241a4452901 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 16:33:51 +0200 Subject: [PATCH 011/135] data / databuffer fixes --- .../main/java/net/tomp2p/storage/Data.java | 24 ++-- .../java/net/tomp2p/storage/DataBuffer.java | 131 +++++++----------- .../src/main/java/net/tomp2p/utils/Utils.java | 57 ++++---- .../main/java/net/tomp2p/dht/FutureGet.java | 2 +- .../java/net/tomp2p/dht/FutureRemove.java | 2 +- .../main/java/net/tomp2p/dht/FutureSend.java | 2 +- .../tomp2p/synchronization/Instruction.java | 8 +- .../net/tomp2p/synchronization/RArray.java | 58 ++++++++ .../net/tomp2p/synchronization/RSync.java | 8 +- .../net/tomp2p/synchronization/SyncUtils.java | 2 +- .../replication/SynchronizationTest.java | 10 +- 11 files changed, 156 insertions(+), 148 deletions(-) create mode 100644 replication/src/main/java/net/tomp2p/synchronization/RArray.java diff --git a/core/src/main/java/net/tomp2p/storage/Data.java b/core/src/main/java/net/tomp2p/storage/Data.java index 31ff0a2d1..4d7571573 100644 --- a/core/src/main/java/net/tomp2p/storage/Data.java +++ b/core/src/main/java/net/tomp2p/storage/Data.java @@ -467,11 +467,7 @@ public ByteBuf buffer() { } public Object object() throws ClassNotFoundException, IOException { - if(buffer.isHeapBuffer()) { - return Utils.decodeJavaObject(buffer.bytes(), 0, buffer.bytes().length); - } else { - return Utils.decodeJavaObject(buffer); - } + return Utils.decodeJavaObject(buffer); } public long validFromMillis() { @@ -813,7 +809,7 @@ private static boolean hasBasedOn(final int header) { * @return The byte array that is the payload. Here we copy the buffer */ public byte[] toBytes() { - return buffer.bytes(); + return buffer.convertToHeapBuffer(); } /** @@ -900,17 +896,15 @@ public Number160 hash() { } public Data release() { - synchronized (buffer.lockObject()) { - buffer.release(); - } - return this; + buffer.release(); + return this; } - public String refcnt() { - return buffer.refcnt(); - } + public void convertToHeapBuffer() { + buffer.convertToHeapBuffer(); + } public boolean isHeapBuffer() { - return buffer.isHeapBuffer(); - } + return buffer.isHeapBuffer(); + } } diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 185f57c9e..ce5082c8e 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -7,13 +7,15 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class DataBuffer { private final Object lock = new Object(); + private final List buffers; - private byte[] heapBuffer = null; + private volatile byte[] heapBuffer; public DataBuffer() { this(1); @@ -60,20 +62,12 @@ private DataBuffer(final List buffers) { } } - public DataBuffer add(DataBuffer dataBuffer) { - if(isHeapBuffer()) { - throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); - } - synchronized (dataBuffer.lock) { - for (final ByteBuf buf : dataBuffer.buffers) { - if(buf.isReadable()) { - this.buffers.add(buf.duplicate()); - buf.retain(); - } - } + public DataBuffer add(byte[] array, int offset, int length) { + synchronized (lock) { + buffers.add(Unpooled.wrappedBuffer(array, offset, length)); } return this; - } + } /** * From here, work with shallow copies. @@ -81,13 +75,11 @@ public DataBuffer add(DataBuffer dataBuffer) { */ public DataBuffer shallowCopy() { if(isHeapBuffer()) { - throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + throw new RuntimeException("This is now a heapbuffer, cannot copy"); } - final DataBuffer db; synchronized (lock) { - db = new DataBuffer(buffers); + return new DataBuffer(buffers); } - return db; } /** @@ -148,7 +140,7 @@ public ByteBuf toByteBuf() { */ public ByteBuf[] toByteBufs() { if(isHeapBuffer()) { - return new ByteBuf[]{toByteBuf()}; + return new ByteBuf[]{Unpooled.wrappedBuffer(heapBuffer)}; } else { final DataBuffer copy = shallowCopy(); return copy.buffers.toArray(new ByteBuf[0]); @@ -164,7 +156,7 @@ public ByteBuf[] toByteBufs() { */ public int transferTo(final AlternativeCompositeByteBuf buf) { if(isHeapBuffer()) { - throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + throw new RuntimeException("This is now a heapbuffer, cannot transfer"); } final DataBuffer copy = shallowCopy(); int transferred = 0; @@ -177,7 +169,7 @@ public int transferTo(final AlternativeCompositeByteBuf buf) { public int transferFrom(final ByteBuf buf, final int max) { if(isHeapBuffer()) { - throw new RuntimeException("Already a heap buffer, cannot transfer data to it!"); + throw new RuntimeException("This is now a heapbuffer, cannot transfer"); } final int readable = buf.readableBytes(); final int index = buf.readerIndex(); @@ -224,8 +216,10 @@ public int hashCode() { return Arrays.hashCode(heapBuffer); } else { int hash = 42; - for(ByteBuf buf:buffers) { - hash ^= buf.hashCode(); + synchronized (lock) { + for(ByteBuf buf:buffers) { + hash ^= buf.hashCode(); + } } return hash; } @@ -241,28 +235,13 @@ public boolean equals(final Object obj) { } final DataBuffer m = (DataBuffer) obj; if(isHeapBuffer() && m.isHeapBuffer()) { - return Arrays.equals(m.bytes(), bytes()); + return Arrays.equals(heapBuffer, m.heapBuffer); } else if(!isHeapBuffer() && !m.isHeapBuffer()) { return ByteBufUtil.equals(toByteBuf(), m.toByteBuf()); } else { - throw new RuntimeException("cannot compare head with direct"); + throw new RuntimeException("Cannot compare, as DataBuffer is of mixed type: head and direct buffer"); } } - - /*@Override - protected void finalize() throws Throwable { - // work on the original buffer, no worries about threading as we are the - // finalizer - try { - for (ByteBuf buf : buffers) { - buf.release(); - } - } catch (Throwable t) { - throw t; - } finally { - super.finalize(); - } - }*/ /** * If you plan to use PooledByteBufAlloc, then its important to release the @@ -279,68 +258,56 @@ protected void finalize() throws Throwable { */ public DataBuffer release() { synchronized (lock) { - releaseIntern(); - } - return this; - } - - private DataBuffer releaseIntern() { - boolean allReleased = true; - for (ByteBuf buf : buffers) { - if(!buf.release() && allReleased) { - allReleased = false; + for (ByteBuf buf : buffers) { + buf.release(); } - } - if(allReleased) { buffers.clear(); } return this; } - - public boolean isHeapBuffer() { - synchronized (lock) { - return heapBuffer != null && buffers.size() == 0; - } - } /** * Converts the ByteBuf (most likely a direct buffer) to a heap buffer. Once * its converted it most of the methods for manipulating the data in this * class will not work */ - public byte[] bytes() { - final List bufs = bufferList(); - int size = 0; - for (ByteBuffer buf : bufs) { - size += buf.remaining(); + public byte[] convertToHeapBuffer() { + if(heapBuffer != null) { + return heapBuffer; } + final byte[] heapBuffer; synchronized (lock) { - if (isHeapBuffer()) { - return heapBuffer; + int length = 0; + for (final ByteBuf buffer : buffers) { + length += buffer.writerIndex(); } - - heapBuffer = new byte[size]; + heapBuffer = new byte[length]; int offset = 0; - for (ByteBuffer bb : bufs) { - final int length = bb.remaining(); - bb.get(heapBuffer, offset, length); - offset += length; + for (final ByteBuf buffer : buffers) { + final int len = buffer.readableBytes(); + buffer.readBytes(heapBuffer, offset, len); + offset += len; + } + + //release + for (ByteBuf buf : buffers) { + buf.release(); } - releaseIntern(); + buffers.clear(); + + //create new + this.heapBuffer = heapBuffer; return heapBuffer; } } + + public boolean isHeapBuffer() { + synchronized (lock) { + return heapBuffer != null && buffers.size() == 0; + } + } - public Object lockObject() { - return lock; + public byte[] heapBuffer() { + return heapBuffer; } - - public String refcnt() { - ByteBuf b = buffers.get(0); - if(b != null) { - return ""+b.refCnt(); - - } - return ""; - } } diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index c5d292526..0183494d4 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -148,12 +148,11 @@ public static Number160 makeSHAHash(ByteBuffer buffer) { return new Number160(); } } - - public static Number160 makeSHAHash(DataBuffer buffer) { + + public static Number160 makeSHAHash(List bufferList) { try { MessageDigest md = MessageDigest.getInstance("SHA-1"); - DataBuffer copy = buffer.shallowCopy(); - for (ByteBuffer byteBuffer : copy.bufferList()) { + for (ByteBuffer byteBuffer : bufferList) { md.update(byteBuffer); } byte[] digest = md.digest(); @@ -164,6 +163,15 @@ public static Number160 makeSHAHash(DataBuffer buffer) { } } + public static Number160 makeSHAHash(DataBuffer buffer) { + if(buffer.isHeapBuffer()) { + return makeSHAHash(buffer.heapBuffer()); + } else { + DataBuffer copy = buffer.shallowCopy(); + return makeSHAHash(copy.bufferList()); + } + } + public static Number160 makeSHAHash(byte[] buffer) { return makeSHAHash(ByteBuffer.wrap(buffer)); } @@ -276,46 +284,29 @@ public static Object decodeJavaObject(ByteBuf channelBuffer) throws ClassNotFoun ois.close(); return obj; } - - public static synchronized Object decodeJavaObject(DataBuffer dataBuffer) throws ClassNotFoundException, IOException { - - List buffers = dataBuffer.shallowCopy().bufferList(); - int count = buffers.size(); + + public static synchronized Object decodeJavaObject(List buffers) throws ClassNotFoundException, IOException { + int count = buffers.size(); Vector is = new Vector(count); for (ByteBuffer byteBuffer : buffers) { is.add(createInputStream(byteBuffer)); } SequenceInputStream sis = new SequenceInputStream(is.elements()); ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(sis)); - //TODO: investigate this issue - /*ObjectInputStream ois = null; - try { - ois = new ObjectInputStream(new BufferedInputStream(sis)); - } catch (Throwable t) { - for (ByteBuffer byteBuffer : buffers) { - byteBuffer.rewind(); - int read = byteBuffer.capacity(); - byteBuffer.limit(read); - byte me[] = new byte[read]; - byteBuffer.get(me); - System.err.println("wrong array1 ("+System.identityHashCode(byteBuffer)+"): "+Arrays.toString(me)); - - if(dataBuffer.test!=null) { - dataBuffer.test.readerIndex(0); - dataBuffer.test.writerIndex(dataBuffer.test.capacity()); - me = new byte[dataBuffer.test.readableBytes()]; - dataBuffer.test.readBytes(me); - System.err.println("wrong array2 ("+System.identityHashCode(byteBuffer)+"): "+Arrays.toString(me)); - } - - } - t.printStackTrace(); - }*/ Object obj = ois.readObject(); ois.close(); return obj; } + public static synchronized Object decodeJavaObject(DataBuffer dataBuffer) throws ClassNotFoundException, IOException { + + if(dataBuffer.isHeapBuffer()) { + return decodeJavaObject(dataBuffer.heapBuffer(), 0, dataBuffer.length()); + } else { + return decodeJavaObject(dataBuffer.shallowCopy().bufferList()); + } + } + public static InputStream createInputStream(final ByteBuffer buf) { return new InputStream() { @Override diff --git a/dht/src/main/java/net/tomp2p/dht/FutureGet.java b/dht/src/main/java/net/tomp2p/dht/FutureGet.java index b65e44394..0ed7ec7f4 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureGet.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureGet.java @@ -92,7 +92,7 @@ public void receivedData(final Map> rawData, f if(convertToHeapBuffer) { for(Map map:rawData.values()) { for(Data data:map.values()) { - data.toBytes(); + data.convertToHeapBuffer(); } } } diff --git a/dht/src/main/java/net/tomp2p/dht/FutureRemove.java b/dht/src/main/java/net/tomp2p/dht/FutureRemove.java index c4c1e89b0..12420dda7 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureRemove.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureRemove.java @@ -130,7 +130,7 @@ public void receivedData(final Map> rawData, F if(convertToHeapBuffer) { for(Map map:rawData.values()) { for(Data data:map.values()) { - data.toBytes(); + data.convertToHeapBuffer(); } } } diff --git a/dht/src/main/java/net/tomp2p/dht/FutureSend.java b/dht/src/main/java/net/tomp2p/dht/FutureSend.java index 55c964892..43111cdd0 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureSend.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureSend.java @@ -82,7 +82,7 @@ public void directData1(final Map rawChannels, FutureDo if(convertToHeapBuffer) { for(DataBuffer data:rawChannels.values()) { - data.bytes(); + data.convertToHeapBuffer(); } } diff --git a/replication/src/main/java/net/tomp2p/synchronization/Instruction.java b/replication/src/main/java/net/tomp2p/synchronization/Instruction.java index 44e94d738..ab95cf811 100644 --- a/replication/src/main/java/net/tomp2p/synchronization/Instruction.java +++ b/replication/src/main/java/net/tomp2p/synchronization/Instruction.java @@ -18,8 +18,6 @@ import java.io.Serializable; -import net.tomp2p.storage.DataBuffer; - /** * Class that holds the instructions what to do with the differences. * @@ -31,14 +29,14 @@ public class Instruction implements Serializable { private static final long serialVersionUID = 112641683009283845L; private final int reference; - private final DataBuffer literal; + private final RArray literal; public Instruction(int reference) { this.reference = reference; this.literal = null; } - public Instruction (DataBuffer literal) { + public Instruction (RArray literal) { this.reference = -1; this.literal = literal; } @@ -47,7 +45,7 @@ public int reference() { return reference; } - public DataBuffer literal() { + public RArray literal() { return literal; } diff --git a/replication/src/main/java/net/tomp2p/synchronization/RArray.java b/replication/src/main/java/net/tomp2p/synchronization/RArray.java new file mode 100644 index 000000000..ee4f3d482 --- /dev/null +++ b/replication/src/main/java/net/tomp2p/synchronization/RArray.java @@ -0,0 +1,58 @@ +package net.tomp2p.synchronization; + +import io.netty.buffer.Unpooled; +import net.tomp2p.storage.AlternativeCompositeByteBuf; +import net.tomp2p.storage.DataBuffer; + +public class RArray { + + private final byte[] array; + private final int offset; + private final int length; + + private final DataBuffer dataBuffer; + + public RArray(byte[] array, int offset, int length) { + this.array = array; + this.offset = offset; + this.length = length; + this.dataBuffer = null; + } + + public RArray(DataBuffer dataBuffer) { + this.array = null; + this.offset = -1; + this.length = -1; + this.dataBuffer = dataBuffer; + } + + public byte[] array() { + return array; + } + + public int offset() { + return offset; + } + + public int length() { + return length; + } + + public DataBuffer dataBuffer() { + return dataBuffer; + } + + public boolean hasDataBuffer() { + return dataBuffer != null; + } + + public void transferTo(AlternativeCompositeByteBuf buf) { + if(hasDataBuffer()) { + dataBuffer.transferTo(buf); + } else { + buf.addComponent(Unpooled.wrappedBuffer(array, offset, length)); + } + + } + +} diff --git a/replication/src/main/java/net/tomp2p/synchronization/RSync.java b/replication/src/main/java/net/tomp2p/synchronization/RSync.java index bceb8a771..78c364c26 100644 --- a/replication/src/main/java/net/tomp2p/synchronization/RSync.java +++ b/replication/src/main/java/net/tomp2p/synchronization/RSync.java @@ -122,7 +122,7 @@ public static List instructions(byte[] array, List checks final int reference = matches(wcs, array, offset, remaining, checksums); if (reference != -1) { if (offset > lastRefFound) { - result.add(new Instruction(new DataBuffer(array, lastRefFound, offset - lastRefFound))); + result.add(new Instruction(new RArray(array, lastRefFound, offset - lastRefFound))); } result.add(new Instruction(reference)); @@ -143,7 +143,7 @@ public static List instructions(byte[] array, List checks } if (length > lastRefFound) { - result.add(new Instruction(new DataBuffer(array, lastRefFound, length - lastRefFound))); + result.add(new Instruction(new RArray(array, lastRefFound, length - lastRefFound))); } return result; @@ -168,9 +168,9 @@ public static DataBuffer reconstruct(byte[] value, List instruction if (ref != -1) { int offset = blockSize * ref; int remaining = Math.min(blockSize, value.length - offset); - result.add(new DataBuffer(value, offset, remaining)); + result.add(value, offset, remaining); } else { - result.add(instruction.literal()); + result.add(instruction.literal().array(), instruction.literal().offset(), instruction.literal().length()); } } return result; diff --git a/replication/src/main/java/net/tomp2p/synchronization/SyncUtils.java b/replication/src/main/java/net/tomp2p/synchronization/SyncUtils.java index ad959f775..d0219866c 100644 --- a/replication/src/main/java/net/tomp2p/synchronization/SyncUtils.java +++ b/replication/src/main/java/net/tomp2p/synchronization/SyncUtils.java @@ -41,7 +41,7 @@ public static List decodeInstructions(ByteBuf buf) { final int remaining = Math.min(length, buf.readableBytes()); DataBuffer literal = new DataBuffer(buf.slice(buf.readerIndex(), remaining)); buf.skipBytes(remaining); - result.add(new Instruction(literal)); + result.add(new Instruction(new RArray(literal))); } } return result; diff --git a/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java b/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java index 0561f9542..269fddcc4 100644 --- a/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java +++ b/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java @@ -94,7 +94,7 @@ public void testGetReconstructedValueStatic0() throws IOException, NoSuchAlgorit List checksums = RSync.checksums(oldValue, size); List instructions = RSync.instructions(newValue, checksums, size); DataBuffer reconstructedValue = RSync.reconstruct(oldValue, instructions, size); - Assert.assertArrayEquals(newValue, reconstructedValue.bytes()); + Assert.assertArrayEquals(newValue, reconstructedValue.convertToHeapBuffer()); } @Test @@ -106,7 +106,7 @@ public void testGetReconstructedValueStatic1() throws IOException, NoSuchAlgorit List checksums = RSync.checksums(oldValue, size); List instructions = RSync.instructions(newValue, checksums, size); DataBuffer reconstructedValue = RSync.reconstruct(oldValue, instructions, size); - Assert.assertArrayEquals(newValue, reconstructedValue.bytes()); + Assert.assertArrayEquals(newValue, reconstructedValue.convertToHeapBuffer()); } @Test @@ -118,7 +118,7 @@ public void testGetReconstructedValueStatic2() throws IOException, NoSuchAlgorit List checksums = RSync.checksums(oldValue, size); List instructions = RSync.instructions(newValue, checksums, size); DataBuffer reconstructedValue = RSync.reconstruct(oldValue, instructions, size); - Assert.assertArrayEquals(newValue, reconstructedValue.bytes()); + Assert.assertArrayEquals(newValue, reconstructedValue.convertToHeapBuffer()); } @Test @@ -132,7 +132,7 @@ public void testGetReconstructedValueStatic3() throws IOException, NoSuchAlgorit Assert.assertEquals(4, instructions.size()); DataBuffer reconstructedValue = RSync.reconstruct(oldValue, instructions, size); - Assert.assertArrayEquals(newValue, reconstructedValue.bytes()); + Assert.assertArrayEquals(newValue, reconstructedValue.convertToHeapBuffer()); } @Test @@ -186,7 +186,7 @@ private void testGetReconstructedValueDynamic0(int counter) throws IOException { DataBuffer reconstructedValue = RSync.reconstruct(oldValue.getBytes(), instructions, size); - Assert.assertArrayEquals(newValue.getBytes(), reconstructedValue.bytes()); + Assert.assertArrayEquals(newValue.getBytes(), reconstructedValue.convertToHeapBuffer()); } @Test From df8ac183dc664c5ed1bb9560aab6029315b30251 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 17:26:28 +0200 Subject: [PATCH 012/135] only release the data we won't use anymore --- .../java/net/tomp2p/dht/StorageLayer.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 5b2d65cdd..517b490b5 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -379,7 +379,13 @@ private NavigableMap getLatestInternal(NavigableMap removed = deletePredecessors(latest.getKey(), tmp); + //only release the keys we have removed, the data we put in result will be released when sent + for(Map.Entry entry:removed.entrySet()) { + if(!entry.getKey().equals(latest.getKey())) { + entry.getValue().release(); + } + } } return result; } @@ -399,15 +405,15 @@ private NavigableMap filterCopy(final NavigableMap sortedMap) { + private NavigableMap deletePredecessors(Number640 key, NavigableMap sortedMap) { final List toRemove = new ArrayList(); + final NavigableMap removed = new TreeMap(); toRemove.add(key); - //int counter = 0; while(!toRemove.isEmpty()) { - //System.err.println("counter: "+ (counter++)); - final Data version = sortedMap.remove(toRemove.remove(0)); + final Number640 key2 = toRemove.remove(0); + final Data version = sortedMap.remove(key2); if(version != null) { - version.release(); + removed.put(key2, version); // check if version has been already deleted && // check if version is initial version if(!version.basedOnSet().isEmpty()) { for (final Number160 basedOnKey : version.basedOnSet()) { @@ -416,6 +422,7 @@ private void deletePredecessors(Number640 key, NavigableMap sor } } } + return removed; } public NavigableMap get() { From d230fae9de2ea46b9e51df0e59fe2efe7c878c04 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 8 Jun 2015 17:53:37 +0200 Subject: [PATCH 013/135] remove cast exception fixed --- dht/src/main/java/net/tomp2p/dht/StorageMemory.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java index 451e58284..ca3f8c14f 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java @@ -25,6 +25,7 @@ import java.util.NavigableMap; import java.util.Set; import java.util.SortedMap; +import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; @@ -99,8 +100,9 @@ public Data remove(Number640 key, boolean returnData) { @Override public NavigableMap remove(Number640 fromKey, Number640 toKey) { - ConcurrentSkipListMap tmp = (ConcurrentSkipListMap) dataMap.subMap(fromKey, true, toKey, true); - final NavigableMap retVal = tmp.clone(); + NavigableMap tmp = dataMap.subMap(fromKey, true, toKey, true); + final NavigableMap retVal = new TreeMap(); + retVal.putAll(tmp); tmp.clear(); return retVal; } From 2c5c6314e8fc0dfd62e9440d5a83f3a2355888c8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 9 Jun 2015 11:06:26 +0200 Subject: [PATCH 014/135] awaitListener now also waits until the operation finishes --- .../java/net/tomp2p/futures/BaseFuture.java | 4 +-- .../net/tomp2p/futures/BaseFutureImpl.java | 35 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/net/tomp2p/futures/BaseFuture.java b/core/src/main/java/net/tomp2p/futures/BaseFuture.java index e2743f0e0..03d8fbcb1 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFuture.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFuture.java @@ -156,7 +156,7 @@ public enum FutureType { FutureType type(); /** - * Waits until all the listener finished. This may include the release of resources. + * Waits until the operation is complete and all the listener finished. This may include the release of resources. * * @return this * @throws InterruptedException @@ -165,7 +165,7 @@ public enum FutureType { BaseFuture awaitListeners() throws InterruptedException; /** - * Waits uninterruptedly until all the listener finished. This may include the release of resources. + * Waits uninterruptedly until the operation is complete and all the listener finished. This may include the release of resources. * * @return this */ diff --git a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java index 1f6b9ab97..07a0b3e17 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java @@ -93,8 +93,8 @@ public K await() throws InterruptedException { while (!completed) { lock.wait(); } - return self; } + return self; } @Override @@ -108,8 +108,8 @@ public K awaitUninterruptibly() { LOG.debug("interrupted, but ignoring", e); } } - return self; } + return self; } @Override @@ -270,24 +270,36 @@ protected boolean completedAndNotify() { public K awaitListeners() throws InterruptedException { boolean wait = false; synchronized (lock) { - if(listeners.size() > 0) { + checkDeadlock(); + while (!completed) { + lock.wait(); + } + if(listeners.size() > 0) { wait = true; } - } + } if(wait) { listenersFinished.await(); } - return self; + return self; } @Override public K awaitListenersUninterruptibly() { boolean wait = false; synchronized (lock) { - if(listeners.size() > 0) { + checkDeadlock(); + while (!completed) { + try { + lock.wait(); + } catch (final InterruptedException e) { + LOG.debug("interrupted, but ignoring", e); + } + } + if(listeners.size() > 0) { wait = true; - } - } + } + } while(wait) { try { listenersFinished.await(); @@ -296,7 +308,7 @@ public K awaitListenersUninterruptibly() { LOG.debug("interrupted, but ignoring", e); } } - return self; + return self; } @Override @@ -360,8 +372,11 @@ protected void notifyListeners() { for (final BaseFutureListener listener : listeners) { callOperationComplete(listener); } + + synchronized (lock) { + listeners.clear(); + } listenersFinished.countDown(); - listeners.clear(); // all events are one time events. It cannot happen that you get // notified twice } From ca2c24b8a52c67352c7754fca71310a86b21a10c Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 9 Jun 2015 14:49:50 +0200 Subject: [PATCH 015/135] improved memory handling --- .../main/java/net/tomp2p/message/Decoder.java | 4 +- .../java/net/tomp2p/rpc/DirectDataRPC.java | 1 + .../storage/AlternativeCompositeByteBuf.java | 2 +- .../java/net/tomp2p/storage/DataBuffer.java | 76 ++++++++++--------- .../test/java/net/tomp2p/rpc/TestDirect.java | 1 + .../net/tomp2p/dht/DistributedHashTable.java | 7 +- 6 files changed, 47 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index 648493bf7..568f69e29 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -35,7 +35,6 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.rpc.SimpleBloomFilter; -import net.tomp2p.storage.AlternativeCompositeByteBuf; import net.tomp2p.storage.Data; import net.tomp2p.storage.DataBuffer; import net.tomp2p.utils.Utils; @@ -511,8 +510,7 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, return false; } - ByteBuf buf2 = AlternativeCompositeByteBuf.compBuffer(byteBufAllocator, buffer.toByteBufs()); - message.buffer(new Buffer(buf2, bufferSize)); + message.buffer(new Buffer(buffer.toByteBuf(), bufferSize)); lastContent = contentTypes.poll(); bufferSize = -1; bufferTransferred = 0; diff --git a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java index ce84309da..b359fd525 100644 --- a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java @@ -160,6 +160,7 @@ public void handleResponse(final Message message, PeerConnection peerConnection, responseMessage.buffer(new Buffer(Unpooled.wrappedBuffer(me))); } } + requestBuffer.buffer().release(); } responder.response(responseMessage); } diff --git a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java index f6efdec45..666c79d5e 100644 --- a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java +++ b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java @@ -293,7 +293,7 @@ public AlternativeCompositeByteBuf addComponent(boolean fillBuffer, ByteBuf... b if (buffers == null) { throw new NullPointerException("buffers"); } - for (ByteBuf b : buffers) { + for (final ByteBuf b : buffers) { if (b == null) { break; } diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index ce5082c8e..9a17342e4 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -7,7 +7,6 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; public class DataBuffer { @@ -52,12 +51,14 @@ public DataBuffer(final ByteBuf buf) { } } - private DataBuffer(final List buffers) { + private DataBuffer(final List buffers, boolean retain) { this.buffers = new ArrayList(buffers.size()); for (final ByteBuf buf : buffers) { if(buf.isReadable()) { this.buffers.add(buf.duplicate()); - buf.retain(); + if(retain) { + buf.retain(); + } } } } @@ -68,20 +69,49 @@ public DataBuffer add(byte[] array, int offset, int length) { } return this; } + + /** + * Shallow copy, needs to be released! + * @return + */ + public DataBuffer shallowCopy() { + if(isHeapBuffer()) { + throw new RuntimeException("This is now a heapbuffer, cannot copy"); + } + synchronized (lock) { + return new DataBuffer(buffers, true); + } + } /** * From here, work with shallow copies. * @return Shallow copy of this DataBuffer. */ - public DataBuffer shallowCopy() { + private DataBuffer shallowCopyIntern() { if(isHeapBuffer()) { throw new RuntimeException("This is now a heapbuffer, cannot copy"); } synchronized (lock) { - return new DataBuffer(buffers); + return new DataBuffer(buffers, false); } } + /** + * @return The length of the data that is backed by the data buffer + */ + public int length() { + if(isHeapBuffer()) { + return heapBuffer.length; + } else { + int length = 0; + final DataBuffer copy = shallowCopyIntern(); + for (final ByteBuf buffer : copy.buffers) { + length += buffer.writerIndex(); + } + return length; + } + } + /** * Always make a copy with shallowCopy before using the buffer directly. * This buffer is not thread safe! @@ -94,7 +124,7 @@ public List bufferList() { nioBuffers = new ArrayList(1); nioBuffers.add(ByteBuffer.wrap(heapBuffer)); } else { - final DataBuffer copy = shallowCopy(); + final DataBuffer copy = shallowCopyIntern(); nioBuffers = new ArrayList(copy.buffers.size()); for (final ByteBuf buf : copy.buffers) { for (final ByteBuffer bb : buf.nioBuffers()) { @@ -104,22 +134,6 @@ public List bufferList() { } return nioBuffers; } - - /** - * @return The length of the data that is backed by the data buffer - */ - public int length() { - if(isHeapBuffer()) { - return heapBuffer.length; - } else { - int length = 0; - final DataBuffer copy = shallowCopy(); - for (final ByteBuf buffer : copy.buffers) { - length += buffer.writerIndex(); - } - return length; - } - } /** * @return The wrapped ByteBuf backed by the buffers stored in here. The buffer is @@ -129,23 +143,11 @@ public ByteBuf toByteBuf() { if(isHeapBuffer()) { return Unpooled.wrappedBuffer(heapBuffer); } else { - final DataBuffer copy = shallowCopy(); + final DataBuffer copy = shallowCopyIntern(); + //wrap does a slice, so a derived buffer, not increasing ref count return Unpooled.wrappedBuffer(copy.buffers.toArray(new ByteBuf[0])); } } - - /** - * @return The ByteBuf arrays backed by the buffers stored in here. The buffer is - * not deep copied here. - */ - public ByteBuf[] toByteBufs() { - if(isHeapBuffer()) { - return new ByteBuf[]{Unpooled.wrappedBuffer(heapBuffer)}; - } else { - final DataBuffer copy = shallowCopy(); - return copy.buffers.toArray(new ByteBuf[0]); - } - } /** * Transfers the data from this buffer the CompositeByteBuf. @@ -158,7 +160,7 @@ public int transferTo(final AlternativeCompositeByteBuf buf) { if(isHeapBuffer()) { throw new RuntimeException("This is now a heapbuffer, cannot transfer"); } - final DataBuffer copy = shallowCopy(); + final DataBuffer copy = shallowCopyIntern(); int transferred = 0; for (final ByteBuf buffer : copy.buffers) { buf.addComponent(buffer); diff --git a/core/src/test/java/net/tomp2p/rpc/TestDirect.java b/core/src/test/java/net/tomp2p/rpc/TestDirect.java index 8588b3f71..519d22049 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestDirect.java +++ b/core/src/test/java/net/tomp2p/rpc/TestDirect.java @@ -112,6 +112,7 @@ public void operationComplete(FutureResponse future) throws Exception { // the future object might be null if the future failed, // e.g due to shutdown System.err.println(future.responseMessage().buffer(0).object()); + future.responseMessage().buffer(0).buffer().release(); } }); } diff --git a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java index 68a4e29a4..29c3047f1 100644 --- a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java +++ b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java @@ -177,12 +177,14 @@ public void interMediateResponse(FutureResponse future) { if (builder.isRaw()) { rawChannels.put(future.request().recipient(), new DataBuffer(future.responseMessage().buffer(0).buffer())); + future.responseMessage().buffer(0).buffer().release(); } else { try { rawObjects.put( future.request().recipient(), future.responseMessage().buffer(0) .object()); + future.responseMessage().buffer(0).buffer().release(); } catch (ClassNotFoundException e) { rawObjects.put( future.request().recipient(), e); @@ -633,9 +635,8 @@ private static > void loopRec(final NavigableSet fp = new FutureForkJoin(Math.min(min, active), false, futures); fp.addListener(new BaseFutureAdapter>() { From 03a46f8d22640fe01b169a4ac26511b99fdc3732 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 9 Jun 2015 15:30:22 +0200 Subject: [PATCH 016/135] memory improvments --- dht/src/main/java/net/tomp2p/dht/StorageLayer.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 517b490b5..c1e946b35 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -261,15 +261,18 @@ public Map> putAll(final NavigableMap dataMa NavigableMap tmp = backend.subMap(minVersion, maxVersion); tmp = filterCopy(tmp, -1, true); NavigableMap heads = getLatestInternal(tmp); - if(heads.size() > 1) { - for(Number640 fork:heads.keySet()) { - if(retVal.containsKey(fork)) { - retVal.put(fork, PutStatus.VERSION_FORK); + + final boolean forked = heads.size() > 1; + for(final Map.Entry entry:heads.entrySet()) { + if(forked) { + if(retVal.containsKey(entry.getKey())) { + retVal.put(entry.getKey(), PutStatus.VERSION_FORK); } } + entry.getValue().release(); } - //now remove versions + //now remove old versions if (maxVersions > 0) { NavigableMap versions = backend.subMap(minVersion, maxVersion); From 67b41073f5a8dd51e3c2332f11b6fc6b031ca370 Mon Sep 17 00:00:00 2001 From: tbocek Date: Tue, 9 Jun 2015 22:04:50 +0200 Subject: [PATCH 017/135] copy data to heapbuffer by default --- .../net/tomp2p/relay/android/TestRelay.java | 10 +- .../java/net/tomp2p/futures/FutureDirect.java | 101 ++++++++++++++---- .../net/tomp2p/futures/FutureResponse.java | 48 ++++++++- .../tomp2p/p2p/builder/SendDirectBuilder.java | 10 +- .../java/net/tomp2p/rpc/DirectDataRPC.java | 19 ++-- .../test/java/net/tomp2p/p2p/TestRelay.java | 7 +- .../test/java/net/tomp2p/rpc/TestDirect.java | 8 +- .../test/java/net/tomp2p/relay/TestRelay.java | 10 +- 8 files changed, 162 insertions(+), 51 deletions(-) diff --git a/android/src/test/java/net/tomp2p/relay/android/TestRelay.java b/android/src/test/java/net/tomp2p/relay/android/TestRelay.java index 59bd459e2..44f55168e 100644 --- a/android/src/test/java/net/tomp2p/relay/android/TestRelay.java +++ b/android/src/test/java/net/tomp2p/relay/android/TestRelay.java @@ -276,18 +276,18 @@ public Object reply(PeerAddress sender, Object obj) throws Exception { FutureDirect fd = unreachablePeer2.sendDirect(unreachablePeer1.peerAddress()).object(request).start() .awaitUninterruptibly(); - System.err.println("got msg from: " + fd.futureResponse().responseMessage().sender()); + System.err.println("got msg from: " + fd.responseMessage().sender()); Assert.assertEquals(response, fd.object()); // make sure we did not receive it from the unreachable peer with port 13337 // System.err.println(fd.getWrappedFuture()); // TODO: this case is true for relay // Assert.assertEquals(fd.wrappedFuture().responseMessage().senderSocket().getPort(), 4001); // TODO: this case is true for rcon - Assert.assertEquals(unreachablePeer1.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(unreachablePeer1.peerID(), fd.responseMessage().sender().peerId()); Assert.assertTrue(test1.get()); Assert.assertFalse(test2.get()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.futureResponse().responseMessage().sender() + Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.responseMessage().sender() .peerSocketAddresses().size()); } finally { if (unreachablePeer1 != null) { @@ -343,7 +343,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { Assert.assertEquals(response, fd.object()); // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(unreachablePeer.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(unreachablePeer.peerID(), fd.responseMessage().sender().peerId()); } finally { if (unreachablePeer != null) { unreachablePeer.shutdown().await(); @@ -395,7 +395,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { Assert.assertEquals(response, fd.object()); // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(receiver.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(receiver.peerID(), fd.responseMessage().sender().peerId()); } finally { if (unreachablePeer != null) { unreachablePeer.shutdown().await(); diff --git a/core/src/main/java/net/tomp2p/futures/FutureDirect.java b/core/src/main/java/net/tomp2p/futures/FutureDirect.java index 16791a4db..ad9fc9fb0 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDirect.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDirect.java @@ -1,43 +1,102 @@ package net.tomp2p.futures; +import io.netty.buffer.Unpooled; + import java.io.IOException; import net.tomp2p.message.Buffer; +import net.tomp2p.message.Message; -public class FutureDirect extends FutureWrapper2 { +public class FutureDirect extends FutureResponse { + + final private boolean isRaw; + private boolean convertToHeapBuffer = true; + private Object object = null; + private Buffer buffer = null; + + public FutureDirect(Message requestMessage, boolean isRaw) { + super(requestMessage); + this.isRaw = isRaw; + self(this); + } - private final FutureResponse futureResponse; + @Override + public FutureDirect response(Message responseMessage) { + + synchronized (lock) { + if (!completedAndNotify()) { + return this; + } + if (responseMessage != null) { + this.responseMessage = responseMessage; + // if its ok or nok, the communication was successful. + // Everything else is a failure in communication + type = futureSuccessEvaluator().evaluate(request(), responseMessage); + reason = responseMessage.type().toString(); + + if(convertToHeapBuffer) { + if(isRaw) { + int len = responseMessage.buffer(0).buffer().readableBytes(); + byte[] me = new byte[len]; + responseMessage.buffer(0).buffer().readBytes(me); + buffer = new Buffer(Unpooled.wrappedBuffer(me)); + } else { + try { + object = responseMessage().buffer(0).object(); + responseMessage().buffer(0).buffer().release(); + } catch (ClassNotFoundException e) { + type = FutureType.FAILED; + reason = e.toString(); + } catch (IOException e) { + type = FutureType.FAILED; + reason = e.toString(); + } + } + } + + } else { + type = FutureType.OK; + reason = "Nothing to deliver..."; + } + } + notifyListeners(); + return this; + } - public FutureDirect(String failed) { - super(new FutureResponse(null)); - self(this); - this.futureResponse = wrappedFuture(); - futureResponse.failed(failed); - failed(failed); + @Override + public FutureDirect failed(String failed) { + super.failed(failed); + return this; } - public FutureDirect(FutureResponse futureResponse) { - super(futureResponse); - self(this); - this.futureResponse = futureResponse; - waitFor(); + @Override + public FutureDirect awaitUninterruptibly() { + super.awaitUninterruptibly(); + return this; } - public Buffer buffer() { + + public Buffer buffer() { synchronized (lock) { - return futureResponse.responseMessage().buffer(0); + if(buffer == null) { + int len = responseMessage().buffer(0).buffer().readableBytes(); + byte[] me = new byte[len]; + responseMessage().buffer(0).buffer().readBytes(me); + buffer = new Buffer(Unpooled.wrappedBuffer(me)); + responseMessage().buffer(0).buffer().release(); + } + return buffer; } } public Object object() throws ClassNotFoundException, IOException { synchronized (lock) { - return buffer() != null ? buffer().object() : null; + if(object == null) { + object = responseMessage().buffer(0).object(); + responseMessage().buffer(0).buffer().release(); + } + return object; } } - - public FutureResponse futureResponse() { - return futureResponse; - } - } diff --git a/core/src/main/java/net/tomp2p/futures/FutureResponse.java b/core/src/main/java/net/tomp2p/futures/FutureResponse.java index 5c5d17291..50861ca91 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureResponse.java +++ b/core/src/main/java/net/tomp2p/futures/FutureResponse.java @@ -17,9 +17,16 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Map; +import net.tomp2p.message.Buffer; +import net.tomp2p.message.DataMap; import net.tomp2p.message.Message; +import net.tomp2p.message.TrackerData; +import net.tomp2p.peers.Number640; +import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.RTT; +import net.tomp2p.storage.Data; /** * Each response has one request messages. The corresponding response message is set only if the request has been @@ -34,7 +41,7 @@ public class FutureResponse extends BaseFutureImpl { private final FutureSuccessEvaluator futureSuccessEvaluator; // the reply to this request - private Message responseMessage; + protected Message responseMessage; private boolean reponseLater = false; @@ -213,4 +220,43 @@ public String toString() { public RTT getRoundTripTime() { return roundTripTime; } + + public FutureResponse releaseResponseMessage() { + releaseMessage(responseMessage); + return this; + } + + public FutureResponse releaseRequestMessage() { + releaseMessage(requestMessage); + return this; + } + + public FutureResponse release() { + releaseMessage(responseMessage); + releaseMessage(requestMessage); + return this; + } + + private FutureResponse releaseMessage(Message message) { + if(message != null) { + for(Buffer buffer:message.bufferList()) { + buffer.buffer().release(); + } + for(DataMap dataMap:message.dataMapList()) { + for(Map.Entry entry: dataMap.dataMap().entrySet()) { + entry.getValue().release(); + } + } + for(TrackerData trackerData:message.trackerDataList()) { + for(Map.Entry entry: trackerData.peerAddresses().entrySet()) { + entry.getValue().release(); + } + } + } + return this; + } + + public FutureSuccessEvaluator futureSuccessEvaluator() { + return futureSuccessEvaluator; + } } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java index 552871eae..92f4dc70a 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/SendDirectBuilder.java @@ -27,6 +27,7 @@ import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; +import net.tomp2p.message.Message; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.SendDirectBuilderI; @@ -35,7 +36,7 @@ public class SendDirectBuilder implements ConnectionConfiguration, SendDirectBuilderI, SignatureBuilder { - private static final FutureDirect FUTURE_REQUEST_SHUTDOWN = new FutureDirect("Peer is shutting down."); + private static final FutureDirect FUTURE_REQUEST_SHUTDOWN = new FutureDirect(null, false).failed("Peer is shutting down."); private final Peer peer; @@ -172,8 +173,11 @@ public FutureDirect start() { futureChannelCreator = peer.connectionBean().reservation() .create(isForceUDP() ? 1 : 0, isForceUDP() ? 0 : 1); } + + Message message = peer.directDataRPC().sendInternal0(remotePeer, this); + final FutureDirect futureResponse = new FutureDirect(message, isRaw()); - final RequestHandler request = peer.directDataRPC().sendInternal(remotePeer, this); + final RequestHandler request = peer.directDataRPC().sendInternal(futureResponse, this); if (keepAlive) { if (peerConnection != null) { sendDirectRequest(request, peerConnection); @@ -208,7 +212,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio }); } - return new FutureDirect(request.futureResponse()); + return futureResponse; } private static void sendDirectRequest(final RequestHandler request, final PeerConnection peerConnection) { diff --git a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java index b359fd525..beb469502 100644 --- a/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/DirectDataRPC.java @@ -46,6 +46,12 @@ public DirectDataRPC(PeerBean peerBean, ConnectionBean connectionBean) { super(peerBean, connectionBean); register(RPC.Commands.DIRECT_DATA.getNr()); } + + public Message sendInternal0(final PeerAddress remotePeer, + final SendDirectBuilderI sendDirectBuilder) { + return createMessage(remotePeer, RPC.Commands.DIRECT_DATA.getNr(), + sendDirectBuilder.isRaw() ? Type.REQUEST_1 : Type.REQUEST_2); + } /** * Sends data directly to a peer. Make sure you have set up a reply handler. This is an RPC. @@ -53,12 +59,9 @@ public DirectDataRPC(PeerBean peerBean, ConnectionBean connectionBean) { * @param remotePeer * The remote peer to store the data */ - public RequestHandler sendInternal(final PeerAddress remotePeer, - final SendDirectBuilderI sendDirectBuilder) { - final Message message = createMessage(remotePeer, RPC.Commands.DIRECT_DATA.getNr(), - sendDirectBuilder.isRaw() ? Type.REQUEST_1 : Type.REQUEST_2); - final FutureResponse futureResponse = new FutureResponse(message); - + public RequestHandler sendInternal(final FutureResponse futureResponse, + final SendDirectBuilderI sendDirectBuilder) { + Message message = futureResponse.request(); if (sendDirectBuilder.isSign()) { message.publicKeyAndSign(sendDirectBuilder.keyPair()); } @@ -83,7 +86,9 @@ public RequestHandler sendInternal(final PeerAddress remotePeer, public FutureResponse send(final PeerAddress remotePeer, final SendDirectBuilderI sendDirectBuilder, final ChannelCreator channelCreator) { - final RequestHandler requestHandler = sendInternal(remotePeer, sendDirectBuilder); + Message message = sendInternal0(remotePeer, sendDirectBuilder); + final FutureResponse futureResponse = new FutureResponse(message); + final RequestHandler requestHandler = sendInternal(futureResponse, sendDirectBuilder); if (!sendDirectBuilder.isForceUDP()) { return requestHandler.sendTCP(channelCreator); } else { diff --git a/core/src/test/java/net/tomp2p/p2p/TestRelay.java b/core/src/test/java/net/tomp2p/p2p/TestRelay.java index 0b5e1d878..682c103e0 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRelay.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRelay.java @@ -66,12 +66,7 @@ public Object reply(PeerAddress sender, Object request) FutureDirect futureResponse = master.sendDirect(pcMaster) .object("test").start().awaitUninterruptibly(); - System.err.println("testPeerConnection: "+futureResponse); - System.err.println("testPeerConnection: "+futureResponse.failedReason()); - System.err.println("testPeerConnection: "+futureResponse.futureResponse()); - if(futureResponse.futureResponse() != null) { - System.err.println("testPeerConnection: "+futureResponse.futureResponse().responseMessage()); - } + Assert.assertEquals("yoo!", futureResponse.object()); FuturePeerConnection pcSlave = myDirectDataRPC.peerConnection(); diff --git a/core/src/test/java/net/tomp2p/rpc/TestDirect.java b/core/src/test/java/net/tomp2p/rpc/TestDirect.java index 519d22049..898f2403d 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestDirect.java +++ b/core/src/test/java/net/tomp2p/rpc/TestDirect.java @@ -65,6 +65,8 @@ public Object reply(PeerAddress sender, Object request) throws Exception { Object ret = fd1.responseMessage().buffer(0).object(); Assert.assertEquals("yes", ret); + fd1.release(); + fd2.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -103,7 +105,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { SendDirectBuilder sendDirectBuilder = new SendDirectBuilder(sender, (PeerAddress) null); sendDirectBuilder.object((Object) Integer.valueOf(i)); - FutureResponse futureData = sender.directDataRPC().send(recv1.peerAddress(), + final FutureResponse futureData = sender.directDataRPC().send(recv1.peerAddress(), sendDirectBuilder, cc); Utils.addReleaseListener(cc, futureData); futureData.addListener(new BaseFutureAdapter() { @@ -112,9 +114,9 @@ public void operationComplete(FutureResponse future) throws Exception { // the future object might be null if the future failed, // e.g due to shutdown System.err.println(future.responseMessage().buffer(0).object()); - future.responseMessage().buffer(0).buffer().release(); + futureData.release(); } - }); + }); } System.err.println("done"); Thread.sleep(2000); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRelay.java b/nat/src/test/java/net/tomp2p/relay/TestRelay.java index d91f1818b..c17ff4dc6 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRelay.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRelay.java @@ -263,18 +263,18 @@ public Object reply(PeerAddress sender, Object obj) throws Exception { FutureDirect fd = unreachablePeer2.sendDirect(unreachablePeer1.peerAddress()).object(request).start() .awaitUninterruptibly(); - System.err.println("got msg from: " + fd.futureResponse().responseMessage().sender()); + System.err.println("got msg from: " + fd.responseMessage().sender()); Assert.assertEquals(response, fd.object()); // make sure we did not receive it from the unreachable peer with port 13337 // System.err.println(fd.getWrappedFuture()); // TODO: this case is true for relay // Assert.assertEquals(fd.wrappedFuture().responseMessage().senderSocket().getPort(), 4001); // TODO: this case is true for rcon - Assert.assertEquals(unreachablePeer1.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(unreachablePeer1.peerID(), fd.responseMessage().sender().peerId()); Assert.assertTrue(test1.get()); Assert.assertFalse(test2.get()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.futureResponse().responseMessage().sender() + Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.responseMessage().sender() .peerSocketAddresses().size()); } finally { if (unreachablePeer1 != null) { @@ -329,7 +329,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { Assert.assertEquals(response, fd.object()); // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(unreachablePeer.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(unreachablePeer.peerID(), fd.responseMessage().sender().peerId()); } finally { if (unreachablePeer != null) { unreachablePeer.shutdown().await(); @@ -380,7 +380,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { Assert.assertEquals(response, fd.object()); // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(receiver.peerID(), fd.wrappedFuture().responseMessage().sender().peerId()); + Assert.assertEquals(receiver.peerID(), fd.responseMessage().sender().peerId()); } finally { if (unreachablePeer != null) { unreachablePeer.shutdown().await(); From 4c7fde5c8349ad882b81fb37fea18ebd4650905a Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 09:13:16 +0200 Subject: [PATCH 018/135] more memory fixes --- .../java/net/tomp2p/futures/FutureDirect.java | 71 +++++++++++++------ .../net/tomp2p/futures/FutureResponse.java | 2 +- dht/src/test/java/net/tomp2p/dht/TestDHT.java | 2 +- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/net/tomp2p/futures/FutureDirect.java b/core/src/main/java/net/tomp2p/futures/FutureDirect.java index ad9fc9fb0..f917b0736 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDirect.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDirect.java @@ -35,25 +35,7 @@ public FutureDirect response(Message responseMessage) { type = futureSuccessEvaluator().evaluate(request(), responseMessage); reason = responseMessage.type().toString(); - if(convertToHeapBuffer) { - if(isRaw) { - int len = responseMessage.buffer(0).buffer().readableBytes(); - byte[] me = new byte[len]; - responseMessage.buffer(0).buffer().readBytes(me); - buffer = new Buffer(Unpooled.wrappedBuffer(me)); - } else { - try { - object = responseMessage().buffer(0).object(); - responseMessage().buffer(0).buffer().release(); - } catch (ClassNotFoundException e) { - type = FutureType.FAILED; - reason = e.toString(); - } catch (IOException e) { - type = FutureType.FAILED; - reason = e.toString(); - } - } - } + convert(responseMessage); } else { type = FutureType.OK; @@ -64,6 +46,53 @@ public FutureDirect response(Message responseMessage) { return this; } + @Override + public boolean responseLater(Message responseMessage) { + + synchronized (lock) { + if(completed) { + return false; + } + reponseLater = true; + if (responseMessage != null) { + this.responseMessage = responseMessage; + // if its ok or nok, the communication was successful. + // Everything else is a failure in communication + type = futureSuccessEvaluator().evaluate(request(), responseMessage); + reason = responseMessage.type().toString(); + + convert(responseMessage); + } else { + type = FutureType.OK; + reason = "Nothing to deliver..."; + } + } + return true; + } + + private void convert(Message responseMessage) { + if(convertToHeapBuffer && responseMessage.buffer(0)!=null) { + if(isRaw) { + int len = responseMessage.buffer(0).buffer().readableBytes(); + byte[] me = new byte[len]; + responseMessage.buffer(0).buffer().readBytes(me); + buffer = new Buffer(Unpooled.wrappedBuffer(me)); + responseMessage.buffer(0).buffer().release(); + } else { + try { + object = responseMessage.buffer(0).object(); + responseMessage.buffer(0).buffer().release(); + } catch (ClassNotFoundException e) { + type = FutureType.FAILED; + reason = e.toString(); + } catch (IOException e) { + type = FutureType.FAILED; + reason = e.toString(); + } + } + } + } + @Override public FutureDirect failed(String failed) { super.failed(failed); @@ -79,7 +108,7 @@ public FutureDirect awaitUninterruptibly() { public Buffer buffer() { synchronized (lock) { - if(buffer == null) { + if(buffer == null && responseMessage().buffer(0) != null) { int len = responseMessage().buffer(0).buffer().readableBytes(); byte[] me = new byte[len]; responseMessage().buffer(0).buffer().readBytes(me); @@ -92,7 +121,7 @@ public Buffer buffer() { public Object object() throws ClassNotFoundException, IOException { synchronized (lock) { - if(object == null) { + if(object == null && responseMessage().buffer(0) != null) { object = responseMessage().buffer(0).object(); responseMessage().buffer(0).buffer().release(); } diff --git a/core/src/main/java/net/tomp2p/futures/FutureResponse.java b/core/src/main/java/net/tomp2p/futures/FutureResponse.java index 50861ca91..e1615f0fa 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureResponse.java +++ b/core/src/main/java/net/tomp2p/futures/FutureResponse.java @@ -43,7 +43,7 @@ public class FutureResponse extends BaseFutureImpl { // the reply to this request protected Message responseMessage; - private boolean reponseLater = false; + protected boolean reponseLater = false; private final RTT roundTripTime = new RTT(); diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 4833b62ed..1c40a6c92 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -1004,7 +1004,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean complete) }); FutureDirect fd = master.peer().sendDirect(peers[50].peerAddress()).dataBuffer(d).start(); fd.await(); - System.out.println("done1"); + System.out.println("done1 " + fd.failedReason()); Assert.assertEquals(true, fd.isSuccess()); Assert.assertNull(fd.buffer()); // int read = fd.getBuffer().readInt(); From 372332a246acffbe876db2f21e80a55c8507db94 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 09:49:44 +0200 Subject: [PATCH 019/135] properly shutdown dataMap to not see Netty leak exceptions --- .../java/net/tomp2p/futures/FutureDone.java | 2 + dht/src/main/java/net/tomp2p/dht/PeerDHT.java | 11 +++- .../java/net/tomp2p/dht/StorageLayer.java | 63 +++++++++++++------ .../java/net/tomp2p/dht/StorageMemory.java | 3 + 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/net/tomp2p/futures/FutureDone.java b/core/src/main/java/net/tomp2p/futures/FutureDone.java index db7c83e3a..cb1c61ddd 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDone.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDone.java @@ -27,6 +27,8 @@ * @param */ public class FutureDone extends BaseFutureImpl> { + + public static FutureDone SUCCESS = new FutureDone().done(); private K object; diff --git a/dht/src/main/java/net/tomp2p/dht/PeerDHT.java b/dht/src/main/java/net/tomp2p/dht/PeerDHT.java index 6d001748c..9d6fc294d 100644 --- a/dht/src/main/java/net/tomp2p/dht/PeerDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/PeerDHT.java @@ -2,7 +2,9 @@ import net.tomp2p.connection.PeerBean; import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.FutureDone; import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.Shutdown; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; @@ -13,11 +15,18 @@ public class PeerDHT { final private DistributedHashTable dht; final private StorageLayer storageLayer; - PeerDHT(Peer peer, StorageLayer storageLayer, DistributedHashTable dht, StorageRPC storageRPC) { + PeerDHT(final Peer peer, final StorageLayer storageLayer, final DistributedHashTable dht, final StorageRPC storageRPC) { this.peer = peer; this.storageLayer = storageLayer; this.dht = dht; this.storageRPC = storageRPC; + peer.addShutdownListener(new Shutdown() { + @Override + public BaseFuture shutdown() { + storageLayer.close(); + return FutureDone.SUCCESS; + } + }); } public Peer peer() { diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index c1e946b35..cb023d0cb 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -195,7 +195,7 @@ public Map> putAll(final NavigableMap dataMa Data newData = entry.getValue(); if (!securityDomainCheck(key.locationAndDomainKey(), publicKey, publicKey, domainProtection)) { retVal.put(key, PutStatus.FAILED_SECURITY); - entry.getValue().release(); + newData.release(); continue; } @@ -213,7 +213,7 @@ public Map> putAll(final NavigableMap dataMa if (!securityEntryCheck(key.locationAndDomainAndContentKey(), publicKey, dataKey, newData.isProtectedEntry())) { retVal.put(key, PutStatus.FAILED_SECURITY); - entry.getValue().release(); + newData.release(); continue; } @@ -221,18 +221,18 @@ public Map> putAll(final NavigableMap dataMa if (contains) { if(putIfAbsent) { retVal.put(key, PutStatus.FAILED_NOT_ABSENT); - entry.getValue().release(); + newData.release(); continue; } final Data oldData = backend.get(key); if(oldData.isDeleted()) { retVal.put(key, PutStatus.DELETED); - entry.getValue().release(); + newData.release(); continue; } if(!oldData.basedOnSet().equals(newData.basedOnSet())) { retVal.put(key, PutStatus.VERSION_FORK); - entry.getValue().release(); + newData.release(); continue; } } @@ -259,8 +259,8 @@ public Map> putAll(final NavigableMap dataMa Number640 minVersion = new Number640(key, Number160.ZERO); Number640 maxVersion = new Number640(key, Number160.MAX_VALUE); NavigableMap tmp = backend.subMap(minVersion, maxVersion); - tmp = filterCopy(tmp, -1, true); - NavigableMap heads = getLatestInternal(tmp); + tmp = filterCopyOrig(tmp, -1, true); + NavigableMap heads = getLatestInternalOrig(tmp); final boolean forked = heads.size() > 1; for(final Map.Entry entry:heads.entrySet()) { @@ -269,7 +269,6 @@ public Map> putAll(final NavigableMap dataMa retVal.put(entry.getKey(), PutStatus.VERSION_FORK); } } - entry.getValue().release(); } //now remove old versions @@ -366,29 +365,37 @@ public NavigableMap getLatestVersion(Number640 key) { RangeLock.Range lock = lock(key.locationAndDomainAndContentKey()); try { NavigableMap tmp = backend.subMap(key.minVersionKey(), key.maxVersionKey()); - tmp = filterCopy(tmp, -1, true); + tmp = filterCopyOrig(tmp, -1, true); return getLatestInternal(tmp); } finally { lock.unlock(); } } - private NavigableMap getLatestInternal(NavigableMap tmp) { + private NavigableMap getLatestInternal(NavigableMap input) { + // delete all predecessors + NavigableMap result = new TreeMap(); + while (!input.isEmpty()) { + // first entry is a latest version + Entry latest = input.lastEntry(); + // store in results list + result.put(latest.getKey(), latest.getValue().duplicate()); + // delete all predecessors of latest entry + deletePredecessors(latest.getKey(), input); + } + return result; + } + + private NavigableMap getLatestInternalOrig(NavigableMap input) { // delete all predecessors NavigableMap result = new TreeMap(); - while (!tmp.isEmpty()) { + while (!input.isEmpty()) { // first entry is a latest version - Entry latest = tmp.lastEntry(); + Entry latest = input.lastEntry(); // store in results list result.put(latest.getKey(), latest.getValue()); // delete all predecessors of latest entry - NavigableMap removed = deletePredecessors(latest.getKey(), tmp); - //only release the keys we have removed, the data we put in result will be released when sent - for(Map.Entry entry:removed.entrySet()) { - if(!entry.getKey().equals(latest.getKey())) { - entry.getValue().release(); - } - } + deletePredecessors(latest.getKey(), input); } return result; } @@ -407,6 +414,20 @@ private NavigableMap filterCopy(final NavigableMap filterCopyOrig(final NavigableMap tmp, int limit, boolean ascending) { + NavigableMap retVal = new TreeMap(); + int counter = 0; + for(Map.Entry entry : ascending ? tmp.entrySet() : tmp.descendingMap().entrySet()) { + if (!entry.getValue().hasPrepareFlag()) { + if(limit >= 0 && counter++ >= limit) { + break; + } + retVal.put(entry.getKey(), entry.getValue()); + } + } + return retVal; + } + //iterative version private NavigableMap deletePredecessors(Number640 key, NavigableMap sortedMap) { final List toRemove = new ArrayList(); @@ -926,4 +947,8 @@ public Enum putConfirm(PublicKey publicKey, Number640 key, Data newData) { } //TODO: check for FORKS! } + + public void close() { + backend.close(); + } } diff --git a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java index ca3f8c14f..b6a583204 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java @@ -242,6 +242,9 @@ private void removeRevResponsibility(Number160 peerId, Number160 locationKey) { // Misc @Override public void close() { + for(Data data:dataMap.values()) { + data.release(); + } dataMap.clear(); protectedMap.clear(); timeoutMap.clear(); From f8a2945530d3d216e0106cf268f775e504d41450 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 10:52:30 +0200 Subject: [PATCH 020/135] print out which method is being tested --- .../tomp2p/connection/TestReservation.java | 11 +++++ .../java/net/tomp2p/futures/TestFutures.java | 11 +++++ .../java/net/tomp2p/message/TestMessage.java | 11 +++++ .../message/TestMessageHeaderCodec.java | 11 +++++ .../java/net/tomp2p/p2p/TestAnnounce.java | 12 +++++ .../java/net/tomp2p/p2p/TestBootstrap.java | 12 +++++ .../java/net/tomp2p/p2p/TestBroadcast.java | 11 +++++ .../java/net/tomp2p/p2p/TestConnection.java | 11 +++++ .../test/java/net/tomp2p/p2p/TestDirect.java | 12 +++++ .../java/net/tomp2p/p2p/TestMaintenance.java | 12 +++++ .../test/java/net/tomp2p/p2p/TestQuit.java | 12 +++++ .../tomp2p/p2p/TestRTTRoutingComparator.java | 11 +++++ .../test/java/net/tomp2p/p2p/TestRelay.java | 11 +++++ .../test/java/net/tomp2p/p2p/TestRouting.java | 11 +++++ .../java/net/tomp2p/p2p/TestStatistics.java | 11 +++++ .../java/net/tomp2p/p2p/real/TestIPv6.java | 11 +++++ .../net/tomp2p/p2p/real/TestShutdown.java | 11 +++++ .../java/net/tomp2p/peers/TestFilter.java | 12 +++++ .../java/net/tomp2p/peers/TestLocalMap.java | 11 +++++ .../java/net/tomp2p/peers/TestNumber160.java | 11 +++++ .../net/tomp2p/peers/TestPeerAddress.java | 11 +++++ .../java/net/tomp2p/peers/TestPeerMap.java | 11 +++++ .../java/net/tomp2p/rpc/TestBloomFilter.java | 11 +++++ .../test/java/net/tomp2p/rpc/TestDirect.java | 11 +++++ .../java/net/tomp2p/rpc/TestNeighbor.java | 11 +++++ .../test/java/net/tomp2p/rpc/TestPing.java | 11 +++++ .../java/net/tomp2p/rpc/TestRealPing.java | 11 +++++ .../java/net/tomp2p/rpc/TestReservation.java | 13 ++++-- .../java/net/tomp2p/storage/TestData.java | 12 +++++ .../test/java/net/tomp2p/utils/TestCache.java | 12 +++++ .../test/java/net/tomp2p/utils/TestUtils.java | 12 +++++ dht/src/test/java/net/tomp2p/dht/TestDHT.java | 11 +++++ .../java/net/tomp2p/dht/TestEvaluation.java | 11 +++++ dht/src/test/java/net/tomp2p/dht/TestH2H.java | 11 +++++ .../java/net/tomp2p/dht/TestRangeLock.java | 13 +++++- .../java/net/tomp2p/dht/TestRealNetwork.java | 11 +++++ .../java/net/tomp2p/dht/TestSecurity.java | 11 +++++ .../test/java/net/tomp2p/dht/TestSend.java | 11 +++++ .../java/net/tomp2p/dht/TestSinglePeer.java | 21 --------- .../test/java/net/tomp2p/dht/TestStorage.java | 11 +++++ .../java/net/tomp2p/dht/TestStorageDHT.java | 44 +++++++++++++++++-- .../dht/TestStorageMemoryReplication.java | 11 +++++ 42 files changed, 489 insertions(+), 29 deletions(-) delete mode 100644 dht/src/test/java/net/tomp2p/dht/TestSinglePeer.java diff --git a/core/src/test/java/net/tomp2p/connection/TestReservation.java b/core/src/test/java/net/tomp2p/connection/TestReservation.java index 4b93a1366..a5e3fd212 100644 --- a/core/src/test/java/net/tomp2p/connection/TestReservation.java +++ b/core/src/test/java/net/tomp2p/connection/TestReservation.java @@ -46,7 +46,11 @@ import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Test the connection reservation. @@ -70,6 +74,13 @@ public class TestReservation { private EventLoopGroup workerGroup; + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Before public void createSink() throws IOException { Bindings bindings = new Bindings().addAddress(InetAddress.getByName("127.0.0.1")); diff --git a/core/src/test/java/net/tomp2p/futures/TestFutures.java b/core/src/test/java/net/tomp2p/futures/TestFutures.java index b30e03889..d590ca417 100644 --- a/core/src/test/java/net/tomp2p/futures/TestFutures.java +++ b/core/src/test/java/net/tomp2p/futures/TestFutures.java @@ -25,7 +25,11 @@ import net.tomp2p.peers.Number160; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Test the correctness and the performance of futures. @@ -41,6 +45,13 @@ public class TestFutures { private int steps = RONUDS / SUB; private final Set done = new HashSet(); private final ExecutorService e = Executors.newFixedThreadPool(10); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Tests the performance of sequential processing as a base. diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index 36c60b154..d12917904 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -60,7 +60,11 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -86,6 +90,13 @@ public class TestMessage { private static final int BIT_16 = 256 * 256; private static final Random RND = new Random(SEED); private static final DSASignatureFactory factory = new DSASignatureFactory(); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void compositeBufferTest1() { diff --git a/core/src/test/java/net/tomp2p/message/TestMessageHeaderCodec.java b/core/src/test/java/net/tomp2p/message/TestMessageHeaderCodec.java index 2da2510e4..1853231d8 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessageHeaderCodec.java +++ b/core/src/test/java/net/tomp2p/message/TestMessageHeaderCodec.java @@ -5,9 +5,20 @@ import net.tomp2p.message.Message.Content; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestMessageHeaderCodec { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testContentTypeCodec() { diff --git a/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java b/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java index f9e02aea5..29eca26df 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java +++ b/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java @@ -14,9 +14,21 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestAnnounce { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + /** * Start with -Djava.net.preferIPv4Stack=true * @throws Exception diff --git a/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java b/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java index dcec436f2..3e854e1f6 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java +++ b/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java @@ -13,9 +13,21 @@ import net.tomp2p.peers.PeerAddress; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestBootstrap { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testBootstrapDiscover() throws Exception { final Random rnd = new Random(42); diff --git a/core/src/test/java/net/tomp2p/p2p/TestBroadcast.java b/core/src/test/java/net/tomp2p/p2p/TestBroadcast.java index 1776b491d..b148fd9f7 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestBroadcast.java +++ b/core/src/test/java/net/tomp2p/p2p/TestBroadcast.java @@ -7,10 +7,21 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestBroadcast { private final static Random RND = new Random(42); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testBroadcastTCP() throws Exception { diff --git a/core/src/test/java/net/tomp2p/p2p/TestConnection.java b/core/src/test/java/net/tomp2p/p2p/TestConnection.java index c356376a5..fdda54b3f 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestConnection.java +++ b/core/src/test/java/net/tomp2p/p2p/TestConnection.java @@ -23,10 +23,21 @@ import net.tomp2p.utils.Pair; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; //TODO: find out why the shutdown takes 2 seconds public class TestConnection { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void test() throws Exception { diff --git a/core/src/test/java/net/tomp2p/p2p/TestDirect.java b/core/src/test/java/net/tomp2p/p2p/TestDirect.java index 022764671..1da101877 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestDirect.java +++ b/core/src/test/java/net/tomp2p/p2p/TestDirect.java @@ -8,9 +8,21 @@ import net.tomp2p.rpc.ObjectDataReply; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestDirect { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testDirectMessage1() throws Exception { Peer sender = null; diff --git a/core/src/test/java/net/tomp2p/p2p/TestMaintenance.java b/core/src/test/java/net/tomp2p/p2p/TestMaintenance.java index 6937f505a..574d5418e 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestMaintenance.java +++ b/core/src/test/java/net/tomp2p/p2p/TestMaintenance.java @@ -7,9 +7,21 @@ import net.tomp2p.futures.BaseFuture; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestMaintenance { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testMaintenance() throws Exception { final Random rnd = new Random(42L); diff --git a/core/src/test/java/net/tomp2p/p2p/TestQuit.java b/core/src/test/java/net/tomp2p/p2p/TestQuit.java index f61a6ecc4..d551b864a 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestQuit.java +++ b/core/src/test/java/net/tomp2p/p2p/TestQuit.java @@ -11,9 +11,21 @@ import net.tomp2p.peers.PeerAddress; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestQuit { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testGracefulhalt() throws Exception { Peer sender = null; diff --git a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java index 0fc217aa8..47c57ed51 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java @@ -19,9 +19,20 @@ import net.tomp2p.peers.RTT; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestRTTRoutingComparator { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Two PeerStatistic with the same PeerIDs should compare to 0 (equality) diff --git a/core/src/test/java/net/tomp2p/p2p/TestRelay.java b/core/src/test/java/net/tomp2p/p2p/TestRelay.java index 682c103e0..7e216ae67 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRelay.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRelay.java @@ -16,7 +16,11 @@ import net.tomp2p.rpc.ObjectDataReply; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +29,13 @@ public class TestRelay { private static final Logger LOG = LoggerFactory.getLogger(TestRelay.class); private final static Random rnd = new Random(42L); + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testLoop() throws Exception { for(int i=0;i<100;i++) { diff --git a/core/src/test/java/net/tomp2p/p2p/TestRouting.java b/core/src/test/java/net/tomp2p/p2p/TestRouting.java index ee6b3ba1f..d0e86665d 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRouting.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRouting.java @@ -26,13 +26,24 @@ import org.junit.Assert; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestRouting { private static final Logger LOG = LoggerFactory.getLogger(TestRouting.class); final private static Random rnd = new Random(43L); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testMerge() throws UnknownHostException { diff --git a/core/src/test/java/net/tomp2p/p2p/TestStatistics.java b/core/src/test/java/net/tomp2p/p2p/TestStatistics.java index a6377d0f1..00fc28f79 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestStatistics.java +++ b/core/src/test/java/net/tomp2p/p2p/TestStatistics.java @@ -27,11 +27,22 @@ import net.tomp2p.peers.PeerMapConfiguration; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestStatistics { private static final Number160 ID = new Number160("0x1"); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testCountPeers1() throws UnknownHostException { diff --git a/core/src/test/java/net/tomp2p/p2p/real/TestIPv6.java b/core/src/test/java/net/tomp2p/p2p/real/TestIPv6.java index 921f78ea4..ff97d5cd7 100644 --- a/core/src/test/java/net/tomp2p/p2p/real/TestIPv6.java +++ b/core/src/test/java/net/tomp2p/p2p/real/TestIPv6.java @@ -34,7 +34,11 @@ import net.tomp2p.peers.PeerAddress; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * This class is not suitable for automated integration testing, since it @@ -45,6 +49,13 @@ public class TestIPv6 { private final int port = 4000; private final String ipSuperPeer = "2001:620:10:10c1:201:6cff:feca:426d"; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Starts the server (super peer). diff --git a/core/src/test/java/net/tomp2p/p2p/real/TestShutdown.java b/core/src/test/java/net/tomp2p/p2p/real/TestShutdown.java index d7d237647..96081b79c 100644 --- a/core/src/test/java/net/tomp2p/p2p/real/TestShutdown.java +++ b/core/src/test/java/net/tomp2p/p2p/real/TestShutdown.java @@ -8,11 +8,22 @@ import net.tomp2p.peers.Number160; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestShutdown { private Random rnd = new Random(); private Peer peer; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; public TestShutdown() throws IOException { boolean isConnected = false; diff --git a/core/src/test/java/net/tomp2p/peers/TestFilter.java b/core/src/test/java/net/tomp2p/peers/TestFilter.java index 2f391643a..d51fcd346 100644 --- a/core/src/test/java/net/tomp2p/peers/TestFilter.java +++ b/core/src/test/java/net/tomp2p/peers/TestFilter.java @@ -7,9 +7,21 @@ import net.tomp2p.Utils2; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestFilter { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testIPv4Filter1() throws UnknownHostException { PeerIPFilter filter = new PeerIPFilter(32, 128); diff --git a/core/src/test/java/net/tomp2p/peers/TestLocalMap.java b/core/src/test/java/net/tomp2p/peers/TestLocalMap.java index b11e95c93..e1b70e144 100644 --- a/core/src/test/java/net/tomp2p/peers/TestLocalMap.java +++ b/core/src/test/java/net/tomp2p/peers/TestLocalMap.java @@ -5,12 +5,23 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestLocalMap { private PeerAddress[] addresses; + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Before public void setup() { addresses = new PeerAddress[2]; diff --git a/core/src/test/java/net/tomp2p/peers/TestNumber160.java b/core/src/test/java/net/tomp2p/peers/TestNumber160.java index 15e7e4c86..a55e1651b 100644 --- a/core/src/test/java/net/tomp2p/peers/TestNumber160.java +++ b/core/src/test/java/net/tomp2p/peers/TestNumber160.java @@ -21,10 +21,21 @@ import java.util.concurrent.ConcurrentSkipListSet; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestNumber160 { private final Random rnd = new Random(); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testLength() { diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java index 4c35b24df..bbadffa13 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java @@ -24,7 +24,11 @@ import java.util.Random; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Test the serialization and deserialization of PeerAddress. @@ -36,6 +40,13 @@ public class TestPeerAddress { private static final int SEED = 1; private static final int BIT_16 = 256 * 256; private static final Random RND = new Random(SEED); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Test serialization and deserialization of PeerAddress. diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerMap.java b/core/src/test/java/net/tomp2p/peers/TestPeerMap.java index dcc5ee6f1..6b4843ce8 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerMap.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerMap.java @@ -34,11 +34,22 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestPeerMap { private static final Number160 ID = new Number160("0x1"); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testDifference() throws UnknownHostException { diff --git a/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java b/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java index ac055b00f..a4521628d 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java +++ b/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java @@ -24,7 +24,11 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Test the counting bloom filter and the regular bloom filter. @@ -37,6 +41,13 @@ public class TestBloomFilter { private final int bfSize = 40; private final int bfSizeLarge = 200; + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testEmptyBloomfilter() { SimpleBloomFilter bloomFilter = new SimpleBloomFilter(0, 0); diff --git a/core/src/test/java/net/tomp2p/rpc/TestDirect.java b/core/src/test/java/net/tomp2p/rpc/TestDirect.java index 898f2403d..c7605d28a 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestDirect.java +++ b/core/src/test/java/net/tomp2p/rpc/TestDirect.java @@ -25,9 +25,20 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestDirect { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testDirectMessage1() throws Exception { diff --git a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java index 9d5e61e03..6f10a8192 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java +++ b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java @@ -30,12 +30,23 @@ import net.tomp2p.rpc.NeighborRPC.SearchValues; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestNeighbor { public static final int PORT_TCP = 5001; public static final int PORT_UDP = 5002; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testNeigbhor() throws Exception { diff --git a/core/src/test/java/net/tomp2p/rpc/TestPing.java b/core/src/test/java/net/tomp2p/rpc/TestPing.java index 5bb36a9de..860198730 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestPing.java +++ b/core/src/test/java/net/tomp2p/rpc/TestPing.java @@ -15,13 +15,24 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestPing { static Bindings bindings = new Bindings(); static { //bindings.addInterface("lo"); } + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testPingTCP() throws Exception { diff --git a/core/src/test/java/net/tomp2p/rpc/TestRealPing.java b/core/src/test/java/net/tomp2p/rpc/TestRealPing.java index c82443a3e..4d7cfc4ad 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestRealPing.java +++ b/core/src/test/java/net/tomp2p/rpc/TestRealPing.java @@ -35,7 +35,11 @@ import org.junit.Assert; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * This is not an automated test and needs manual interaction. Thus by default these tests are disabled. @@ -48,6 +52,13 @@ public class TestRealPing { private static final String IP = "127.0.0.1"; private static final int PORT = 5000; private static final int WAIT = 1000000; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Test regular ping. diff --git a/core/src/test/java/net/tomp2p/rpc/TestReservation.java b/core/src/test/java/net/tomp2p/rpc/TestReservation.java index c32e821f2..90dbad1b2 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestReservation.java +++ b/core/src/test/java/net/tomp2p/rpc/TestReservation.java @@ -9,13 +9,20 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestReservation { - /* - * @Test public void testReservationTCPL() throws Exception { for(int i=0;i<100;i++) testReservationTCP(); } - */ + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testReservationTCP() throws Exception { diff --git a/core/src/test/java/net/tomp2p/storage/TestData.java b/core/src/test/java/net/tomp2p/storage/TestData.java index 1601eab94..74e201aea 100644 --- a/core/src/test/java/net/tomp2p/storage/TestData.java +++ b/core/src/test/java/net/tomp2p/storage/TestData.java @@ -16,11 +16,23 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestData { private static final DSASignatureFactory factory = new DSASignatureFactory(); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testData1() throws IOException, ClassNotFoundException, InvalidKeyException, SignatureException { Data data = new Data("test"); diff --git a/core/src/test/java/net/tomp2p/utils/TestCache.java b/core/src/test/java/net/tomp2p/utils/TestCache.java index 05ef118a9..36bdf6028 100644 --- a/core/src/test/java/net/tomp2p/utils/TestCache.java +++ b/core/src/test/java/net/tomp2p/utils/TestCache.java @@ -25,9 +25,21 @@ import java.util.concurrent.atomic.AtomicLong; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestCache { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testCache() throws InterruptedException { ConcurrentCacheMap test = new ConcurrentCacheMap(1, 1024); diff --git a/core/src/test/java/net/tomp2p/utils/TestUtils.java b/core/src/test/java/net/tomp2p/utils/TestUtils.java index f45734418..3e61d7c41 100644 --- a/core/src/test/java/net/tomp2p/utils/TestUtils.java +++ b/core/src/test/java/net/tomp2p/utils/TestUtils.java @@ -20,9 +20,21 @@ import java.util.Collection; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestUtils { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testDifference1() { Collection collection1 = new ArrayList(); diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 1c40a6c92..5591f9533 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -58,7 +58,11 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,6 +70,13 @@ public class TestDHT { final private static Random rnd = new Random(42L); private static final Logger LOG = LoggerFactory.getLogger(TestDHT.class); + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testPutBig() throws Exception { PeerDHT[] peers = null; diff --git a/dht/src/test/java/net/tomp2p/dht/TestEvaluation.java b/dht/src/test/java/net/tomp2p/dht/TestEvaluation.java index 106de9fcc..a32d8d8a5 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestEvaluation.java +++ b/dht/src/test/java/net/tomp2p/dht/TestEvaluation.java @@ -9,9 +9,20 @@ import net.tomp2p.storage.Data; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestEvaluation { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testEvaluationData1() throws Exception { diff --git a/dht/src/test/java/net/tomp2p/dht/TestH2H.java b/dht/src/test/java/net/tomp2p/dht/TestH2H.java index 4b1711c38..b19f0de5c 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestH2H.java +++ b/dht/src/test/java/net/tomp2p/dht/TestH2H.java @@ -25,11 +25,22 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestH2H { private static final DSASignatureFactory factory = new DSASignatureFactory(); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testPut() throws IOException, ClassNotFoundException, diff --git a/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java b/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java index 9657b9fc4..0c618f28e 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java +++ b/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java @@ -4,11 +4,22 @@ import java.util.TreeMap; import java.util.concurrent.CountDownLatch; - import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestRangeLock { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; + @Test public void testRangeLockOverlapping() throws InterruptedException { final CountDownLatch cd = new CountDownLatch(1); diff --git a/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java b/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java index 843df1172..987967292 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java +++ b/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java @@ -28,7 +28,11 @@ import net.tomp2p.storage.Data; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Tests over a real network. Since this requires a real network, the tests are @@ -40,6 +44,13 @@ public class TestRealNetwork { private final int port = 4000; private final String ipSuperPeer = "192.168.1.187"; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Starts the super peer. diff --git a/dht/src/test/java/net/tomp2p/dht/TestSecurity.java b/dht/src/test/java/net/tomp2p/dht/TestSecurity.java index 49b2227df..604072dd3 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestSecurity.java +++ b/dht/src/test/java/net/tomp2p/dht/TestSecurity.java @@ -31,7 +31,11 @@ import net.tomp2p.utils.Utils; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestSecurity { final private static Random rnd = new Random(42L); @@ -45,6 +49,13 @@ public class TestSecurity { Assert.fail("Cannot initialize DSA key pair generator"); } } + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testPublicKeyReceived() throws Exception { diff --git a/dht/src/test/java/net/tomp2p/dht/TestSend.java b/dht/src/test/java/net/tomp2p/dht/TestSend.java index 4b9950374..3cedd4da1 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestSend.java +++ b/dht/src/test/java/net/tomp2p/dht/TestSend.java @@ -11,7 +11,11 @@ import net.tomp2p.rpc.ObjectDataReply; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; /** * Test send over network. @@ -23,6 +27,13 @@ public class TestSend { private static final int PORT = 5000; private static final String ADDR = "192.168.1.x"; private static final RequestP2PConfiguration REQ = new RequestP2PConfiguration(1, 10, 0); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; /** * Start the sender and wait forever. diff --git a/dht/src/test/java/net/tomp2p/dht/TestSinglePeer.java b/dht/src/test/java/net/tomp2p/dht/TestSinglePeer.java deleted file mode 100644 index 6c6c8aba7..000000000 --- a/dht/src/test/java/net/tomp2p/dht/TestSinglePeer.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.tomp2p.dht; - -import java.io.IOException; -import java.util.Random; - -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.storage.Data; - -public class TestSinglePeer { - public static void main(String[] args) throws IOException { - Random rnd = new Random(1); - Peer peer = new PeerBuilder( new Number160( rnd ) ).ports( 4000 ).start(); - PeerDHT peerDHT = new PeerBuilderDHT(peer).start(); - for(int i=0;true;i++) { - peerDHT.put(Number160.ONE).data(new Data("test")).start().awaitUninterruptibly(); - } - //System.out.println("peer up and running : " + peer.peerAddress()); - } -} diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorage.java b/dht/src/test/java/net/tomp2p/dht/TestStorage.java index 43cd7c76e..0d295c522 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorage.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorage.java @@ -18,7 +18,11 @@ import net.tomp2p.storage.Data; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestStorage { final private static Number160 locationKey = new Number160(10); @@ -37,6 +41,13 @@ public class TestStorage { final private Number640 key2 = new Number640(locationKey, domainKey, content2, Number160.ZERO); final private Number640 key3 = new Number640(locationKey, domainKey, content3, Number160.ZERO); final private Number640 key4 = new Number640(locationKey, domainKey, content4, Number160.ZERO); + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; public Storage createStorage() throws IOException { return new StorageMemory(); diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index e39429eb7..d4868c7e8 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -40,7 +40,11 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestStorageDHT { @@ -51,6 +55,13 @@ public class TestStorageDHT { public static final int PORT_TCP = 5001; public static final int PORT_UDP = 5002; + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Before public void before() throws IOException { @@ -156,12 +167,14 @@ public void testAdd() throws Exception { fr.awaitUninterruptibly(); System.err.println(fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); + fr.releaseResponseMessage(); // add a the same data twice fr = smmSender.add(recv1.peerAddress(), addBuilder, cc); fr.awaitUninterruptibly(); System.err.println(fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); - + fr.releaseResponseMessage(); + Number320 key = new Number320(new Number160(33), Number160.createHash("test")); // Set tofetch = new HashSet(); Number640 from = new Number640(key, Number160.ZERO, Number160.ZERO); @@ -241,6 +254,7 @@ public void testStorePut() throws Exception { fr.awaitUninterruptibly(); System.err.println(fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); + fr.releaseResponseMessage(); Number640 key1 = new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO); Data c = storeRecv.get(key1); @@ -260,6 +274,7 @@ public void testStorePut() throws Exception { fr.awaitUninterruptibly(); System.err.println(fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); + fr.releaseResponseMessage(); Map result2 = storeRecv.subMap(key1.minContentKey(), key1.maxContentKey()); Assert.assertEquals(result2.size(), 2); //Number480 search = new Number480(key, new Number160(88)); @@ -312,6 +327,7 @@ public void testStorePutIfAbsent() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); Assert.assertEquals(true, fr.isSuccess()); + fr.releaseResponseMessage(); Number640 key = new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO); Data c = storeRecv.get(key).duplicate(); @@ -331,6 +347,7 @@ public void testStorePutIfAbsent() throws Exception { // we cannot put anything there, since there already is Assert.assertEquals(true, fr.isSuccess()); Map putKeys = fr.responseMessage().keyMapByte(0).keysMap(); + fr.release(); Assert.assertEquals(2, putKeys.size()); Assert.assertEquals(Byte.valueOf((byte)PutStatus.FAILED_NOT_ABSENT.ordinal()), putKeys.values().iterator().next()); Number640 key2 = new Number640(new Number160(33), Number160.createHash("test"), new Number160(88), Number160.ZERO); @@ -378,6 +395,7 @@ public void testStorePutGetTCP() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); + fr.releaseResponseMessage(); // get GetBuilder getBuilder = new GetBuilder(recv1, new Number160(33)); @@ -392,6 +410,7 @@ public void testStorePutGetTCP() throws Exception { Message m = fr.responseMessage(); Map stored = m.dataMap(0).dataMap(); compare(dataMap.dataMap(), stored); + fr.release(); System.err.println("done!"); } finally { if (cc != null) { @@ -437,6 +456,7 @@ public void testStorePutGetUDP() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); Assert.assertEquals(true, fr.isSuccess()); + fr.releaseResponseMessage(); GetBuilder getBuilder = new GetBuilder(recv1, new Number160(33)); getBuilder.domainKey(Number160.createHash("test")); @@ -451,6 +471,7 @@ public void testStorePutGetUDP() throws Exception { Message m = fr.responseMessage(); Map stored = m.dataMap(0).dataMap(); compare(dataMap.dataMap(), stored); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -505,6 +526,7 @@ public void testStorePutRemoveGet() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); + fr.release(); // remove RemoveBuilder removeBuilder = new RemoveBuilder(recv1, new Number160(33)); removeBuilder.domainKey(Number160.createHash("test")); @@ -515,6 +537,7 @@ public void testStorePutRemoveGet() throws Exception { fr.awaitUninterruptibly(); Message m = fr.responseMessage(); Assert.assertEquals(true, fr.isSuccess()); + fr.release(); // check for returned results Map stored = m.dataMap(0).dataMap(); @@ -533,6 +556,7 @@ public void testStorePutRemoveGet() throws Exception { m = fr.responseMessage(); DataMap stored2 = m.dataMap(0); Assert.assertEquals(0, stored2.size()); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -578,6 +602,7 @@ public void testBigStorePut() throws Exception { Assert.assertEquals(true, fr.isSuccess()); KeyMapByte keys = fr.responseMessage().keyMapByte(0); Utils.isSameSets(keys.keysMap().keySet(), dataMap.dataMap().keySet()); + fr.release(); } finally { if (cc != null) { @@ -624,6 +649,7 @@ public void testConcurrentStoreAddGet() throws Exception { System.err.println("failed: " + fr.failedReason()); } Assert.assertEquals(true, fr.isSuccess()); + fr.release(); } res.clear(); cc.shutdown().awaitListenersUninterruptibly(); @@ -687,6 +713,7 @@ public void testBloomFilter() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); + fr.release(); SimpleBloomFilter sbf = new SimpleBloomFilter(100, 1); sbf.add(new Number160(77)); @@ -703,6 +730,7 @@ public void testBloomFilter() throws Exception { Message m = fr.responseMessage(); Map stored = m.dataMap(0).dataMap(); Assert.assertEquals(1, stored.size()); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -746,6 +774,7 @@ public void testBloomFilterDigest() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); fr.awaitUninterruptibly(); + fr.release(); SimpleBloomFilter sbf = new SimpleBloomFilter(100, 2); sbf.add(new Number160(77)); @@ -762,6 +791,7 @@ public void testBloomFilterDigest() throws Exception { Assert.assertEquals(true, fr.isSuccess()); Message m = fr.responseMessage(); Assert.assertEquals(2, m.keyMap640Keys(0).size()); + fr.release(); } finally { if (cc != null) { @@ -777,7 +807,6 @@ public void testBloomFilterDigest() throws Exception { } @Test - // TODO test is not working public void testBigStore2() throws Exception { StorageMemory storeSender = new StorageMemory(); StorageMemory storeRecv = new StorageMemory(); @@ -816,6 +845,7 @@ public void testBigStore2() throws Exception { Data data = recv1.storageLayer() .get(new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO)); Assert.assertEquals(true, data != null); + fr.release(); } finally { @@ -868,6 +898,7 @@ public void testBigStoreGet() throws Exception { fr.awaitUninterruptibly(); Assert.assertEquals(true, fr.isSuccess()); + fr.release(); // GetBuilder getBuilder = new GetBuilder(recv1, new Number160(33)); @@ -883,6 +914,7 @@ public void testBigStoreGet() throws Exception { Number640 key = new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO); Assert.assertEquals(50 * 1024 * 1024, fr.responseMessage().dataMap(0).dataMap().get(key) .length()); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -922,10 +954,11 @@ public void testBigStoreCancel() throws Exception { FutureResponse fr = smmSender.put(recv1.peerAddress(), putBuilder, cc); - Thread.sleep(5); + Thread.sleep(50); fr.cancel(); Assert.assertEquals(false, fr.isSuccess()); System.err.println("good!"); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -977,6 +1010,7 @@ public void testBigStoreGetCancel() throws Exception { fr.awaitUninterruptibly(); System.err.println("XX:" + fr.failedReason()); Assert.assertEquals(true, fr.isSuccess()); + fr.release(); // GetBuilder getBuilder = new GetBuilder(recv1, new Number160(33)); getBuilder.domainKey(Number160.createHash("test")); @@ -985,6 +1019,7 @@ public void testBigStoreGetCancel() throws Exception { fr.cancel(); System.err.println("XX:" + fr.failedReason()); Assert.assertEquals(false, fr.isSuccess()); + fr.release(); } finally { if (cc != null) { cc.shutdown().awaitListenersUninterruptibly(); @@ -1026,6 +1061,7 @@ public void testData480() throws Exception { FutureResponse fr = master.storeRPC().put(slave.peerAddress(), pb, cc); fr.awaitUninterruptibly(); Assert.assertEquals(true, fr.isSuccess()); + fr.release(); GetBuilder gb = master.get(new Number160("0x51")).domainKey(Number160.ZERO); @@ -1034,7 +1070,7 @@ public void testData480() throws Exception { Assert.assertEquals(true, fr.isSuccess()); System.err.println("done"); - + fr.release(); } finally { diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageMemoryReplication.java b/dht/src/test/java/net/tomp2p/dht/TestStorageMemoryReplication.java index 4d7c384b6..5bab3083e 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageMemoryReplication.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageMemoryReplication.java @@ -3,9 +3,20 @@ import net.tomp2p.peers.Number160; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; public class TestStorageMemoryReplication { + + @Rule + public TestRule watcher = new TestWatcher() { + protected void starting(Description description) { + System.out.println("Starting test: " + description.getMethodName()); + } + }; @Test public void testStorageMemoryReplication1() { From ad2d343353f98f8ddc27dad6a750c932d793760b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 11:06:28 +0200 Subject: [PATCH 021/135] release data --- dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index d4868c7e8..73735133c 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -846,6 +846,7 @@ public void testBigStore2() throws Exception { .get(new Number640(new Number160(33), Number160.createHash("test"), new Number160(77), Number160.ZERO)); Assert.assertEquals(true, data != null); fr.release(); + data.release(); } finally { From 87de5811ad04af10d117400a4f0f081df2cadea8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 12:03:28 +0200 Subject: [PATCH 022/135] more memory fixes --- .../main/java/net/tomp2p/connection/PeerCreator.java | 8 -------- core/src/main/java/net/tomp2p/p2p/PeerBuilder.java | 10 ++++++++++ dht/src/test/java/net/tomp2p/dht/TestDHT.java | 6 +++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index 49dfadd77..7de3b3205 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -25,8 +25,6 @@ import java.io.IOException; import java.net.InetAddress; import java.security.KeyPair; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -54,8 +52,6 @@ public class PeerCreator { private final ConnectionBean connectionBean; private final PeerBean peerBean; - private final List childConnections = new ArrayList(); - private final EventLoopGroup workerGroup; private final EventLoopGroup bossGroup; @@ -121,7 +117,6 @@ public PeerCreator(final int p2pId, final Number160 peerId, final KeyPair keyPai * The key pair or null */ public PeerCreator(final PeerCreator parent, final Number160 peerId, final KeyPair keyPair) { - parent.childConnections.add(this); this.workerGroup = parent.workerGroup; this.bossGroup = parent.bossGroup; this.connectionBean = parent.connectionBean; @@ -150,9 +145,6 @@ public FutureDone shutdown() { // shutdown all children if (!master) { - for (PeerCreator peerCreator : childConnections) { - peerCreator.shutdown(); - } return futureServerDone.done(); } // shutdown the timer diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index fce809c2a..5e7ec5915 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -42,6 +42,7 @@ import net.tomp2p.connection.PipelineFilter; import net.tomp2p.connection.Ports; import net.tomp2p.connection.SendBehavior; +import net.tomp2p.futures.BaseFuture; import net.tomp2p.p2p.builder.PingBuilder; import net.tomp2p.peers.LocalMap; import net.tomp2p.peers.Number160; @@ -237,6 +238,15 @@ public Peer start() throws IOException { } final Peer peer = new Peer(p2pID, peerId, peerCreator); + //add shutdown hook to master peer + if (masterPeer != null) { + masterPeer.addShutdownListener(new Shutdown() { + @Override + public BaseFuture shutdown() { + return peer.shutdown(); + } + }); + } PeerBean peerBean = peerCreator.peerBean(); diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 5591f9533..07fa3e498 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -2328,7 +2328,11 @@ private void testForArray(PeerDHT peer, Number160 locationKey, boolean find) { test.get( new Number640(new Number320(locationKey, Number160.createHash("test")), new Number160(5), Number160.ZERO)).length()); - } else + } else { Assert.assertEquals(0, test.size()); + } + for(Map.Entry entry: test.entrySet()) { + entry.getValue().release(); + } } } From 29644f16e99986a4a19ba5ba4e4bdb0bcf4a704d Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 15:26:08 +0200 Subject: [PATCH 023/135] further memory improvements --- .../net/tomp2p/connection/Dispatcher.java | 2 + .../net/tomp2p/connection/RequestHandler.java | 4 ++ .../java/net/tomp2p/connection/Sender.java | 6 +- .../java/net/tomp2p/futures/BaseFuture.java | 15 +---- .../net/tomp2p/futures/BaseFutureImpl.java | 57 +++++++------------ .../net/tomp2p/futures/FutureResponse.java | 2 + .../main/java/net/tomp2p/message/Encoder.java | 3 + .../main/java/net/tomp2p/message/Message.java | 17 ++++++ .../net/tomp2p/dht/DistributedHashTable.java | 4 +- .../main/java/net/tomp2p/dht/FutureGet.java | 7 +++ .../java/net/tomp2p/dht/StorageLayer.java | 6 +- .../main/java/net/tomp2p/dht/StorageRPC.java | 14 ----- dht/src/test/java/net/tomp2p/dht/TestDHT.java | 1 - 13 files changed, 68 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 5a1695291..1cec393a7 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -164,6 +164,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa peerStatusListener.peerFailed(message.sender(), new PeerException(AbortCause.PEER_ERROR, "Wrong P2P version.")); } } + message.release(); return; } @@ -181,6 +182,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa PeerConnection peerConnection = new PeerConnection(message.sender(), new DefaultChannelPromise(ctx.channel()).setSuccess(), heartBeatMillis); myHandler.forwardMessage(message, isUdp ? null : peerConnection, responder); } else { + message.release(); if (LOG.isWarnEnabled()) { printWarnMessage(message); } diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index e2bec9ace..47c2bd3af 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -260,12 +260,14 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo String msg = "Message was not delivered successfully, unknow ID (peer may be offline or unknown RPC handler): " + this.message; exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); + responseMessage.release(); return; } if (responseMessage.type() == Message.Type.EXCEPTION) { String msg = "Message caused an exception on the other side, handle as peer_abort: " + this.message; exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); + responseMessage.release(); return; } if (responseMessage.isRequest()) { @@ -276,6 +278,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo String msg = "Response message [" + responseMessage + "] sent to the node is not the same as we expect. We sent [" + this.message + "]"; exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); + responseMessage.release(); return; } // We need to exclude RCON Messages from the sanity check because we @@ -289,6 +292,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo + this.message + "]. Recipient (" + message.recipient().isRelayed() + ") / Sender (" + responseMessage.sender().isRelayed() + ")"; exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); + responseMessage.release(); return; } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index c612f7eae..464e4efe9 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -782,11 +782,11 @@ public void afterConnect(final FutureResponse futureResponse, final Message mess } LOG.debug("about to connect to {} with channel {}, ff={}", message.recipient(), channelFuture.channel(), fireAndForget); final Cancel connectCancel = createCancel(channelFuture); - futureResponse.addCancel(connectCancel); + futureResponse.setCancel(connectCancel); channelFuture.addListener(new GenericFutureListener() { @Override public void operationComplete(final ChannelFuture future) throws Exception { - futureResponse.removeCancel(connectCancel); + if (future.isSuccess()) { final ChannelFuture writeFuture = future.channel().writeAndFlush(message); afterSend(writeFuture, futureResponse, fireAndForget); @@ -817,11 +817,11 @@ public void operationComplete(final ChannelFuture future) throws Exception { */ private void afterSend(final ChannelFuture writeFuture, final FutureResponse futureResponse, final boolean fireAndForget) { final Cancel writeCancel = createCancel(writeFuture); + futureResponse.setCancel(writeCancel); writeFuture.addListener(new GenericFutureListener() { @Override public void operationComplete(final ChannelFuture future) throws Exception { - futureResponse.removeCancel(writeCancel); if (!future.isSuccess()) { futureResponse.failedLater(future.cause()); reportFailed(futureResponse, future.channel().close()); diff --git a/core/src/main/java/net/tomp2p/futures/BaseFuture.java b/core/src/main/java/net/tomp2p/futures/BaseFuture.java index 03d8fbcb1..f94ae62d7 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFuture.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFuture.java @@ -25,7 +25,7 @@ public interface BaseFuture extends Cancel { * The first state is always INIT and will always end in either OK, FAILED, or CANCEl. */ public enum FutureType { - INIT, OK, FAILED + INIT, OK, FAILED, CANCEL }; /** @@ -198,21 +198,12 @@ public enum FutureType { BaseFuture removeListener(BaseFutureListener listener); /** - * Adds a cancel listener to this future, which is called when cancel is executed. Triggering a cancel does not + * Set a cancel callback to this future, which is called when cancel is executed. Triggering a cancel does not * finish this future. * * @param cancel * The cancel listener * @return this */ - BaseFuture addCancel(Cancel cancel); - - /** - * Removes a cancel listener to this future. Triggering a cancel does not finish this future. - * - * @param cancel - * The cancel listener - * @return This class - */ - BaseFuture removeCancel(Cancel cancel); + BaseFuture setCancel(Cancel cancel); } diff --git a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java index 07a0b3e17..fa591d718 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java @@ -44,7 +44,7 @@ public abstract class BaseFutureImpl implements BaseFuture // While a future is running, the process may add cancellations for faster // cancel operations, e.g. cancel connection attempt - private final List cancels = new ArrayList(0); + private volatile Cancel cancel = null; private final CountDownLatch listenersFinished = new CountDownLatch(1); @@ -61,8 +61,6 @@ public abstract class BaseFutureImpl implements BaseFuture private K self; - private boolean cancel = false; - /** * Default constructor that sets the lock object, which is used for synchronization to this instance. */ @@ -238,7 +236,7 @@ public String failedReason() { final StringBuffer sb = new StringBuffer("Future (compl/canc):"); synchronized (lock) { sb.append(completed).append("/") - .append(cancel).append(", ").append(type.name()) + .append(", ").append(type.name()) .append(", ").append(reason); return sb.toString(); } @@ -369,13 +367,17 @@ protected void notifyListeners() { // There won't be any visibility problem or concurrent modification // because 'ready' flag will be checked against both addListener and // removeListener calls. + // + // This method doesn't need synchronization because: + // 1) This method is always called after synchronized (this) block. + // Hence any listener list modification happens-before this method. + // 2) This method is called only when 'done' is true. Once 'done' + // becomes true, the listener list is never modified - see add/removeListener() for (final BaseFutureListener listener : listeners) { callOperationComplete(listener); } - synchronized (lock) { - listeners.clear(); - } + listeners.clear(); listenersFinished.countDown(); // all events are one time events. It cannot happen that you get // notified twice @@ -392,43 +394,26 @@ public K removeListener(final BaseFutureListener listener) } @Override - public K addCancel(final Cancel cancelListener) { - synchronized (cancels) { - if (cancel) { - cancelListener.cancel(); - } - else { - cancels.add(cancelListener); - } - } - return self; - } - - @Override - public K removeCancel(final Cancel cancelListener) { - synchronized (cancels) { - if (!cancel) { - cancels.remove(cancelListener); + public K setCancel(final Cancel cancel) { + synchronized (lock) { + if (!completed) { + this.cancel = cancel; } - } + } return self; } @Override public void cancel() { - boolean notifyCancel = false; - synchronized (cancels) { - if (!cancel) { - cancel = true; - notifyCancel = true; - } else { + synchronized (lock) { + if (!completedAndNotify()) { return; } + this.type = FutureType.CANCEL; } - if (notifyCancel) { - for (final Cancel cancellable : cancels) { - cancellable.cancel(); - } - } + if(cancel != null) { + cancel.cancel(); + } + notifyListeners(); } } diff --git a/core/src/main/java/net/tomp2p/futures/FutureResponse.java b/core/src/main/java/net/tomp2p/futures/FutureResponse.java index e1615f0fa..0389b2a16 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureResponse.java +++ b/core/src/main/java/net/tomp2p/futures/FutureResponse.java @@ -92,6 +92,7 @@ public FutureResponse emptyResponse() { public FutureResponse response(final Message responseMessage) { synchronized (lock) { if (!completedAndNotify()) { + responseMessage.release(); return this; } if (responseMessage != null) { @@ -112,6 +113,7 @@ public FutureResponse response(final Message responseMessage) { public boolean responseLater(final Message responseMessage) { synchronized (lock) { if(completed) { + responseMessage.release(); return false; } reponseLater = true; diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index 8864c906e..e75f109bd 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -246,6 +246,9 @@ private void encodeData(AlternativeCompositeByteBuf buf, Data data, boolean isCo filteredData.encodeHeader(buf, signatureFactory); filteredData.encodeBuffer(buf); filteredData.encodeDone(buf, signatureFactory, message.privateKey()); + if(isReply) { + filteredData.release(); + } } public Message message() { diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 07524a117..6a414e4e0 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -1269,4 +1269,21 @@ public int estimateSize() { return current; } + + public void release() { + for(DataMap dataMap: dataMapList()) { + for(Data data: dataMap.dataMap().values()) { + data.release(); + } + } + for(Buffer buffer: bufferList()) { + buffer.buffer().release(); + } + for(TrackerData trackerData:trackerDataList()) { + for(Data data:trackerData.peerAddresses().values()) { + data.release(); + } + } + + } } diff --git a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java index 29c3047f1..773736605 100644 --- a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java +++ b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java @@ -27,7 +27,6 @@ import net.tomp2p.connection.ChannelCreator; import net.tomp2p.dht.StorageLayer.PutStatus; -import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; import net.tomp2p.futures.FutureDone; @@ -694,9 +693,10 @@ else if(builder.contentKeys() != null && builder.contentKeys().size() > 1) { private static void cancel(final AtomicReferenceArray futures) { int len = futures.length(); for (int i = 0; i < len; i++) { - BaseFuture baseFuture = futures.get(i); + FutureResponse baseFuture = futures.get(i); if (baseFuture != null) { baseFuture.cancel(); + baseFuture.release(); } } } diff --git a/dht/src/main/java/net/tomp2p/dht/FutureGet.java b/dht/src/main/java/net/tomp2p/dht/FutureGet.java index 0ed7ec7f4..5c365c0ce 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureGet.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureGet.java @@ -95,6 +95,13 @@ public void receivedData(final Map> rawData, f data.convertToHeapBuffer(); } } + for(DigestResult digest:rawDigest.values()) { + if(digest.dataMap() != null) { + for(Data data:digest.dataMap().values()) { + data.convertToHeapBuffer(); + } + } + } } this.rawDigest = rawDigest; diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index cb023d0cb..2f2844696 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -616,7 +616,7 @@ public DigestInfo digest(Number640 from, Number640 to, int limit, boolean ascend RangeLock.Range lock = rangeLock.lock(from, to); try { NavigableMap tmp = backend.subMap(from, to); - tmp = filterCopy(tmp, limit, ascending); + tmp = filterCopyOrig(tmp, limit, ascending); for (Map.Entry entry : tmp.entrySet()) { if (!entry.getValue().hasPrepareFlag()) { digestInfo.put(entry.getKey(), entry.getValue().basedOnSet()); @@ -640,7 +640,7 @@ public DigestInfo digest(Number320 locationAndDomainKey, SimpleBloomFilter tmp = backend.subMap(from, to); - tmp = filterCopy(tmp, limit, ascending); + tmp = filterCopyOrig(tmp, limit, ascending); for (Map.Entry entry : tmp.entrySet()) { if (isBloomFilterAnd) { if (keyBloomFilter == null || keyBloomFilter.contains(entry.getKey().contentKey())) { @@ -909,6 +909,7 @@ public Enum updateMeta(PublicKey publicKey, Number640 key, Data newData) { return PutStatus.NOT_FOUND; } } finally { + newData.release(); lock.unlock(); } } @@ -943,6 +944,7 @@ public Enum putConfirm(PublicKey publicKey, Number640 key, Data newData) { return PutStatus.NOT_FOUND; } } finally { + newData.release(); lock.unlock(); } //TODO: check for FORKS! diff --git a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java index c5ce98454..04997b400 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java @@ -773,20 +773,6 @@ private Message handlePut(final Message message, final Message responseMessage, replicationListener.dataInserted(locationKey); } } - - /*for (Map.Entry entry : toStore.dataMap().entrySet()) { - Enum putStatus = doPut(putIfAbsent, protectDomain, publicKey, entry.getKey(), entry.getValue(), message.isSendSelf()); - result.put(entry.getKey(), (byte) putStatus.ordinal()); - // check the responsibility of the newly added data, do something - // (notify) if we are responsible - if (!entry.getValue().hasPrepareFlag()) { - if ((putStatus == PutStatus.OK || putStatus == PutStatus.VERSION_FORK || putStatus == PutStatus.DELETED) - && replicationListener != null) { - replicationListener.dataInserted(entry.getKey().locationKey(), replicaPut); - } - } - - }*/ responseMessage.type(result.size() == dataSize ? Type.OK : Type.PARTIALLY_OK); responseMessage.keyMapByte(new KeyMapByte(result)); diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 07fa3e498..2fd97d5e2 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -1070,7 +1070,6 @@ public void testObject() throws Exception { //System.out.println("got it"); } finally { if (master != null) { - master.shutdown().awaitUninterruptibly(); master.shutdown().awaitListenersUninterruptibly(); } } From 8bf1ec16cafe456e59eaed1348148923a64f9bff Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 16:39:30 +0200 Subject: [PATCH 024/135] reply removes the data from the message --- .../java/net/tomp2p/message/TestMessage.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index d12917904..eb3c38163 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -208,7 +208,7 @@ public void testEncodeDecode3() throws Exception { // encode public void testEncodeDecode4() throws Exception { Message m1 = Utils2.createDummyMessage(); Random rnd = new Random(42); - m1.type(Message.Type.DENIED); + m1.type(Message.Type.REQUEST_4); m1.setHintSign(); KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); @@ -247,7 +247,7 @@ public void testEncodeDecode4() throws Exception { public void testEncodeDecode5() throws Exception { Message m1 = Utils2.createDummyMessage(); Random rnd = new Random(42); - m1.type(Message.Type.PARTIALLY_OK); + m1.type(Message.Type.REQUEST_2); m1.setHintSign(); KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); @@ -287,7 +287,7 @@ public void testEncodeDecode5() throws Exception { public void testEncodeDecode7() throws Exception { Message m1 = Utils2.createDummyMessage(); Random rnd = new Random(42); - m1.type(Message.Type.PARTIALLY_OK); + m1.type(Message.Type.REQUEST_3); m1.setHintSign(); KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); @@ -385,7 +385,7 @@ public void testBigDataSigned() throws Exception { } @Test - public void testEncodeDecode480Map() throws Exception { // encode + public void testEncodeDecode480MapRep() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); m1.type(Message.Type.PARTIALLY_OK); KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); @@ -403,6 +403,29 @@ public void testEncodeDecode480Map() throws Exception { // encode m1.setDataMap(new DataMap(dataMap)); Message m2 = encodeDecode(m1); Assert.assertEquals(true, m2.publicKey(0) != null); + m2.release(); + compareMessage(m1, m2); + } + + @Test + public void testEncodeDecode480MapReq() throws Exception { // encode + Message m1 = Utils2.createDummyMessage(); + m1.type(Message.Type.REQUEST_1); + KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); + KeyPair pair1 = gen.generateKeyPair(); + m1.publicKeyAndSign(pair1); + NavigableMap dataMap = new TreeMap(); + Random rnd = new Random(42l); + for (int i = 0; i < 1000; i++) { + dataMap.put(new Number640(new Number160(rnd), new Number160(rnd), + new Number160(rnd), new Number160(rnd)), new Data( + new byte[] { (byte) rnd.nextInt(), (byte) rnd.nextInt(), + (byte) rnd.nextInt(), (byte) rnd.nextInt(), + (byte) rnd.nextInt() })); + } + m1.setDataMap(new DataMap(dataMap)); + Message m2 = encodeDecode(m1); + Assert.assertEquals(true, m2.publicKey(0) != null); compareMessage(m1, m2); } From bfdfbf4cb9283cb7ccbffe3b111bc079ebb5692a Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 10 Jun 2015 18:20:11 +0200 Subject: [PATCH 025/135] message can be null --- core/src/main/java/net/tomp2p/futures/FutureResponse.java | 8 ++++++-- core/src/main/java/net/tomp2p/message/TomP2POutbound.java | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/tomp2p/futures/FutureResponse.java b/core/src/main/java/net/tomp2p/futures/FutureResponse.java index 0389b2a16..08397c3b8 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureResponse.java +++ b/core/src/main/java/net/tomp2p/futures/FutureResponse.java @@ -92,7 +92,9 @@ public FutureResponse emptyResponse() { public FutureResponse response(final Message responseMessage) { synchronized (lock) { if (!completedAndNotify()) { - responseMessage.release(); + if(responseMessage != null) { + responseMessage.release(); + } return this; } if (responseMessage != null) { @@ -113,7 +115,9 @@ public FutureResponse response(final Message responseMessage) { public boolean responseLater(final Message responseMessage) { synchronized (lock) { if(completed) { - responseMessage.release(); + if(responseMessage != null) { + responseMessage.release(); + } return false; } reponseLater = true; diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index 06646d097..ff2ce6cd4 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -104,7 +104,9 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { - if (encoder.message() == null) { + //if exeception is not propagated, we may need to wait for the timeout + super.exceptionCaught(ctx, cause); + if (encoder.message() == null) { LOG.error("Exception in encoding when starting.", cause); cause.printStackTrace(); } else if (encoder.message() != null && !encoder.message().isDone()) { From 37f257126e8cc90a0f79ea42e34fb0c9fecbc949 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 10:58:18 +0200 Subject: [PATCH 026/135] further memory improvements --- core/src/main/java/net/tomp2p/message/TomP2POutbound.java | 2 +- core/src/main/java/net/tomp2p/storage/Data.java | 2 +- core/src/main/java/net/tomp2p/storage/DataBuffer.java | 2 +- core/src/main/java/net/tomp2p/utils/Utils.java | 4 ++-- dht/src/main/java/net/tomp2p/dht/StorageLayer.java | 6 ------ dht/src/main/java/net/tomp2p/dht/StorageRPC.java | 4 +++- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index ff2ce6cd4..14a9306d3 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -105,7 +105,7 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { //if exeception is not propagated, we may need to wait for the timeout - super.exceptionCaught(ctx, cause); + //super.exceptionCaught(ctx, cause); if (encoder.message() == null) { LOG.error("Exception in encoding when starting.", cause); cause.printStackTrace(); diff --git a/core/src/main/java/net/tomp2p/storage/Data.java b/core/src/main/java/net/tomp2p/storage/Data.java index 4d7571573..95874e619 100644 --- a/core/src/main/java/net/tomp2p/storage/Data.java +++ b/core/src/main/java/net/tomp2p/storage/Data.java @@ -725,7 +725,7 @@ public String toString() { /** * @return A shallow copy where the data is shared but the reader and writer - * index is not shared + * index is not shared. This will increase the ref count on the buffer */ public Data duplicate() { Data data = new Data(buffer.shallowCopy(), length).publicKey(publicKey) diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 9a17342e4..862cab8c3 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -87,7 +87,7 @@ public DataBuffer shallowCopy() { * From here, work with shallow copies. * @return Shallow copy of this DataBuffer. */ - private DataBuffer shallowCopyIntern() { + public DataBuffer shallowCopyIntern() { if(isHeapBuffer()) { throw new RuntimeException("This is now a heapbuffer, cannot copy"); } diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index 0183494d4..955e11c9f 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -167,7 +167,7 @@ public static Number160 makeSHAHash(DataBuffer buffer) { if(buffer.isHeapBuffer()) { return makeSHAHash(buffer.heapBuffer()); } else { - DataBuffer copy = buffer.shallowCopy(); + DataBuffer copy = buffer.shallowCopyIntern(); return makeSHAHash(copy.bufferList()); } } @@ -303,7 +303,7 @@ public static synchronized Object decodeJavaObject(DataBuffer dataBuffer) throws if(dataBuffer.isHeapBuffer()) { return decodeJavaObject(dataBuffer.heapBuffer(), 0, dataBuffer.length()); } else { - return decodeJavaObject(dataBuffer.shallowCopy().bufferList()); + return decodeJavaObject(dataBuffer.shallowCopyIntern().bufferList()); } } diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 2f2844696..0cc30f83a 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -479,12 +479,6 @@ public NavigableMap get(Number640 from, Number640 to, SimpleBlo while (iterator.hasNext()) { Map.Entry entry = iterator.next(); - if (entry.getValue().hasPrepareFlag()) { - entry.getValue().release(); - iterator.remove(); - continue; - } - if (isBloomFilterAnd) { if (!contentKeyBloomFilter.contains(entry.getKey().contentKey())) { entry.getValue().release(); diff --git a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java index 04997b400..21eac5dbd 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java @@ -888,7 +888,9 @@ private NavigableMap doGet(final Number160 locationKey, final N Number640 max = iterator.next(); result = storageLayer.get(min, max, limit, ascending); - } else if (contentKeyBloomFilter != null && versionBloomFilter != null && contentBloomFilter !=null ) { + } else if (contentKeyBloomFilter != null && !contentKeyBloomFilter.isFull() + && versionBloomFilter != null && !versionBloomFilter.isFull() + && contentBloomFilter !=null && !contentBloomFilter.isFull()) { Number640 min = new Number640(locationKey, domainKey, Number160.ZERO, Number160.ZERO); Number640 max = new Number640(locationKey, domainKey, Number160.MAX_VALUE, Number160.MAX_VALUE); result = storageLayer.get(min, max, contentKeyBloomFilter, versionBloomFilter, contentBloomFilter, limit, ascending, isBloomFilterAnd); From 57edcc296f045759c3b723e911b3959a89b8720b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 11:27:49 +0200 Subject: [PATCH 027/135] fixed bloom filter shortcut --- dht/src/main/java/net/tomp2p/dht/StorageRPC.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java index 21eac5dbd..b77c24063 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java @@ -888,9 +888,8 @@ private NavigableMap doGet(final Number160 locationKey, final N Number640 max = iterator.next(); result = storageLayer.get(min, max, limit, ascending); - } else if (contentKeyBloomFilter != null && !contentKeyBloomFilter.isFull() - && versionBloomFilter != null && !versionBloomFilter.isFull() - && contentBloomFilter !=null && !contentBloomFilter.isFull()) { + } else if (contentKeyBloomFilter != null && versionBloomFilter != null && contentBloomFilter !=null + && (!contentKeyBloomFilter.isFull() || !versionBloomFilter.isFull() || !contentBloomFilter.isFull())) { Number640 min = new Number640(locationKey, domainKey, Number160.ZERO, Number160.ZERO); Number640 max = new Number640(locationKey, domainKey, Number160.MAX_VALUE, Number160.MAX_VALUE); result = storageLayer.get(min, max, contentKeyBloomFilter, versionBloomFilter, contentBloomFilter, limit, ascending, isBloomFilterAnd); From ecad5491d8e979ac2a6552cf1f7c1f44b2624411 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 11:42:58 +0200 Subject: [PATCH 028/135] rsync fixes --- .../java/net/tomp2p/storage/DataBuffer.java | 20 ++++++++++++++++++- .../net/tomp2p/synchronization/RSync.java | 6 ++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 862cab8c3..2dbf77969 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -63,7 +63,19 @@ private DataBuffer(final List buffers, boolean retain) { } } - public DataBuffer add(byte[] array, int offset, int length) { + public DataBuffer append(final List buffers) { + synchronized (lock) { + for (final ByteBuf buf : buffers) { + if(buf.isReadable()) { + this.buffers.add(buf.duplicate()); + buf.retain(); + } + } + } + return this; + } + + public DataBuffer append(byte[] array, int offset, int length) { synchronized (lock) { buffers.add(Unpooled.wrappedBuffer(array, offset, length)); } @@ -95,6 +107,10 @@ public DataBuffer shallowCopyIntern() { return new DataBuffer(buffers, false); } } + + public List bufListIntern() { + return shallowCopyIntern().buffers; + } /** * @return The length of the data that is backed by the data buffer @@ -312,4 +328,6 @@ public boolean isHeapBuffer() { public byte[] heapBuffer() { return heapBuffer; } + + } diff --git a/replication/src/main/java/net/tomp2p/synchronization/RSync.java b/replication/src/main/java/net/tomp2p/synchronization/RSync.java index 78c364c26..d0bea8a8e 100644 --- a/replication/src/main/java/net/tomp2p/synchronization/RSync.java +++ b/replication/src/main/java/net/tomp2p/synchronization/RSync.java @@ -168,9 +168,11 @@ public static DataBuffer reconstruct(byte[] value, List instruction if (ref != -1) { int offset = blockSize * ref; int remaining = Math.min(blockSize, value.length - offset); - result.add(value, offset, remaining); + result.append(value, offset, remaining); + } else if (instruction.literal().hasDataBuffer()) { + result.append(instruction.literal().dataBuffer().bufListIntern()); } else { - result.add(instruction.literal().array(), instruction.literal().offset(), instruction.literal().length()); + result.append(instruction.literal().array(), instruction.literal().offset(), instruction.literal().length()); } } return result; From 8bfcb569f57a898aa153aaf1692b70917798d0ef Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 12:34:05 +0200 Subject: [PATCH 029/135] fixing memory issues --- .../net/tomp2p/connection/ChannelServer.java | 2 +- .../java/net/tomp2p/connection/Sender.java | 2 +- .../main/java/net/tomp2p/message/Decoder.java | 34 ++++++++++++++++--- .../tomp2p/message/TomP2PCumulationTCP.java | 4 ++- .../tomp2p/message/TomP2PSinglePacketUDP.java | 7 ++-- .../java/net/tomp2p/message/TestMessage.java | 4 +-- 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServer.java b/core/src/main/java/net/tomp2p/connection/ChannelServer.java index ba2422383..48d7873ed 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServer.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServer.java @@ -112,7 +112,7 @@ public ChannelServer(final EventLoopGroup bossGroup, final EventLoopGroup worker this.tcpDropConnectionInboundHandler = new DropConnectionInboundHandler(channelServerConfiguration.maxTCPIncomingConnections()); this.udpDropConnectionInboundHandler = new DropConnectionInboundHandler(channelServerConfiguration.maxUDPIncomingConnections()); - this.udpDecoderHandler = new TomP2PSinglePacketUDP(channelServerConfiguration.signatureFactory(), channelServerConfiguration.byteBufAllocator()); + this.udpDecoderHandler = new TomP2PSinglePacketUDP(channelServerConfiguration.signatureFactory()); discoverNetworks.addDiscoverNetworkListener(this); if(timer!=null) { diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 464e4efe9..3004c07b5 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -736,7 +736,7 @@ public Map> configureHandlers(f handlers.put( "decoder", - new Pair(null, new TomP2PSinglePacketUDP(channelClientConfiguration.signatureFactory(), channelClientConfiguration.byteBufAllocator()))); + new Pair(null, new TomP2PSinglePacketUDP(channelClientConfiguration.signatureFactory()))); handlers.put( "encoder", new Pair(null, new TomP2POutbound(channelClientConfiguration.signatureFactory(), channelClientConfiguration.byteBufAllocator()))); diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index 568f69e29..b7da3f1d2 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -1,7 +1,6 @@ package net.tomp2p.message; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.DatagramChannel; import io.netty.util.Attribute; @@ -88,12 +87,9 @@ public class Decoder { private Content lastContent = null; private final SignatureFactory signatureFactory; - - private final ByteBufAllocator byteBufAllocator; - public Decoder(SignatureFactory signatureFactory, final ByteBufAllocator byteBufAllocator) { + public Decoder(SignatureFactory signatureFactory) { this.signatureFactory = signatureFactory; - this.byteBufAllocator = byteBufAllocator; } public boolean decode(ChannelHandlerContext ctx, final ByteBuf buf, InetSocketAddress recipient, @@ -640,4 +636,32 @@ public static void inheritPublicKey(Message message, Data data) { data.publicKey(message.publicKey(0)); } } + + public void release() { + if(message!=null) { + message.release(); + } + //release partial data + if(data != null) { + data.release(); + } + if(dataMap != null) { + for(Data data: dataMap.dataMap().values()) { + data.release(); + } + } + if(buffer != null) { + buffer.release(); + } + + if(currentTrackerData != null) { + currentTrackerData.release(); + } + if(trackerData != null) { + for(Data data: trackerData.peerAddresses().values()) { + data.release(); + } + } + + } } diff --git a/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java b/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java index 2f0554322..45a851900 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java +++ b/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java @@ -25,7 +25,7 @@ public class TomP2PCumulationTCP extends ChannelInboundHandlerAdapter { private int lastId = 0; public TomP2PCumulationTCP(final SignatureFactory signatureFactory, ByteBufAllocator byteBufAllocator) { - decoder = new Decoder(signatureFactory, byteBufAllocator); + decoder = new Decoder(signatureFactory); this.byteBufAllocator = byteBufAllocator; } @@ -95,6 +95,7 @@ private void decoding(final ChannelHandlerContext ctx, @Override public void channelInactive(final ChannelHandlerContext ctx) throws Exception { + decoder.release(); final InetSocketAddress sender = (InetSocketAddress) ctx.channel() .remoteAddress(); try { @@ -121,6 +122,7 @@ public void exceptionCaught(final ChannelHandlerContext ctx, cumulation = null; } Message msg = decoder.message(); + decoder.release(); // don't use getLocalizedMessage() - // http://stackoverflow.com/questions/8699521/any-way-to-ignore-only-connection-reset-by-peer-ioexceptions if (cause.getMessage().equals("Connection reset by peer")) { diff --git a/core/src/main/java/net/tomp2p/message/TomP2PSinglePacketUDP.java b/core/src/main/java/net/tomp2p/message/TomP2PSinglePacketUDP.java index ccaaa00ef..59833bd5f 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2PSinglePacketUDP.java +++ b/core/src/main/java/net/tomp2p/message/TomP2PSinglePacketUDP.java @@ -1,7 +1,6 @@ package net.tomp2p.message; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; @@ -20,11 +19,9 @@ public class TomP2PSinglePacketUDP extends ChannelInboundHandlerAdapter { private static final Logger LOG = LoggerFactory.getLogger(TomP2PSinglePacketUDP.class); private final SignatureFactory signatureFactory; - private final ByteBufAllocator byteBufAllocator; - public TomP2PSinglePacketUDP(final SignatureFactory signatureFactory, ByteBufAllocator byteBufAllocator) { + public TomP2PSinglePacketUDP(final SignatureFactory signatureFactory) { this.signatureFactory = signatureFactory; - this.byteBufAllocator = byteBufAllocator; } @Override @@ -42,7 +39,7 @@ public void channelRead(final ChannelHandlerContext ctx, final Object msg) throw final InetSocketAddress recipient = d.recipient(); try { - Decoder decoder = new Decoder(signatureFactory, byteBufAllocator); + Decoder decoder = new Decoder(signatureFactory); boolean finished = decoder.decode(ctx, buf, recipient, sender); if (finished) { ctx.fireChannelRead(decoder.prepareFinish()); diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index eb3c38163..9811cada3 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -457,7 +457,7 @@ public void serializationTest() throws IOException, ClassNotFoundException, Encoder e = new Encoder(null); AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); e.write(buf, m1, null); - Decoder d = new Decoder(null, AlternativeCompositeByteBuf.UNPOOLED_HEAP); + Decoder d = new Decoder(null); boolean header = d.decodeHeader(buf, new InetSocketAddress(0), new InetSocketAddress(0)); boolean payload = d.decodePayload(buf); @@ -608,7 +608,7 @@ private Message encodeDecode(final Message m1) throws Exception { Encoder encoder = new Encoder(new DSASignatureFactory()); encoder.write(buf, m1, null); ChannelHandlerContext ctx = mockChannelHandlerContext(buf, m2); - Decoder decoder = new Decoder(new DSASignatureFactory(), AlternativeCompositeByteBuf.UNPOOLED_HEAP); + Decoder decoder = new Decoder(new DSASignatureFactory()); decoder.decode(ctx, buf, m1.recipient().createSocketTCP(), m1 .sender().createSocketTCP()); buf.release(); From 573fbcc5affb46976e2b7c6f7c0b0bb242b2fce9 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 12:40:25 +0200 Subject: [PATCH 030/135] Relay Utils calling wrong signature --- nat/src/main/java/net/tomp2p/relay/RelayUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 70e6880a3..dddfd0eb5 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -143,7 +143,7 @@ public static Buffer encodeMessage(Message message, SignatureFactory signatureFa */ public static Message decodeMessage(ByteBuf buf, InetSocketAddress recipient, InetSocketAddress sender, SignatureFactory signatureFactory) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { - Decoder d = new Decoder(signatureFactory, AlternativeCompositeByteBuf.UNPOOLED_HEAP); + Decoder d = new Decoder(signatureFactory); final int readerBefore = buf.readerIndex(); d.decodeHeader(buf, recipient, sender); final boolean donePayload = d.decodePayload(buf); From 2819ff11d4cad5d3cb333d04673b2e247724bdcd Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 13:42:31 +0200 Subject: [PATCH 031/135] shutdown connection after checking for future success --- dht/src/test/java/net/tomp2p/dht/TestDHT.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 2fd97d5e2..28c9bdcab 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -1507,10 +1507,6 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro } Assert.assertEquals(true, bf.isSuccess()); } - for (FuturePeerConnection pc : list3) { - pc.close().awaitUninterruptibly(); - pc.close().awaitListenersUninterruptibly(); - } for (BaseFuture bf : list2) { bf.awaitUninterruptibly(); bf.awaitListenersUninterruptibly(); @@ -1521,6 +1517,10 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro } Assert.assertEquals(true, bf.isSuccess()); } + for (FuturePeerConnection pc : list3) { + pc.close().awaitUninterruptibly(); + pc.close().awaitListenersUninterruptibly(); + } System.out.println("done!!"); } catch (Exception e) { e.printStackTrace(); From e991b0c924589e5f07d87dd790f4808a47d5d576 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 11 Jun 2015 16:14:50 +0200 Subject: [PATCH 032/135] replication fixes --- .../main/java/net/tomp2p/message/Encoder.java | 11 ++++++----- .../java/net/tomp2p/message/TomP2POutbound.java | 4 ++-- .../main/java/net/tomp2p/dht/StorageLayer.java | 16 ++++++++-------- .../tomp2p/replication/IndirectReplication.java | 14 +++++++++----- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index e75f109bd..b57adadde 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -15,6 +15,7 @@ import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.rpc.SimpleBloomFilter; import net.tomp2p.storage.AlternativeCompositeByteBuf; import net.tomp2p.storage.Data; @@ -149,7 +150,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException buf.writeBytes(dataMap.domainKey().toByteArray()); buf.writeBytes(entry.getKey().toByteArray()); buf.writeBytes(dataMap.versionKey().toByteArray()); - encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); + encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } } else { for (Entry entry : dataMap.dataMap().entrySet()) { @@ -157,7 +158,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException buf.writeBytes(entry.getKey().domainKey().toByteArray()); buf.writeBytes(entry.getKey().contentKey().toByteArray()); buf.writeBytes(entry.getKey().versionKey().toByteArray()); - encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest()); + encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } } message.contentReferences().poll(); @@ -219,7 +220,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException byte[] me = entry.getKey().toByteArray(); buf.writeBytes(me); Data data = entry.getValue().duplicate(); - encodeData(buf, data, false, !message.isRequest()); + encodeData(buf, data, false, !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } message.contentReferences().poll(); break; @@ -241,12 +242,12 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException return true; } - private void encodeData(AlternativeCompositeByteBuf buf, Data data, boolean isConvertMeta, boolean isReply) throws InvalidKeyException, SignatureException, IOException { + private void encodeData(AlternativeCompositeByteBuf buf, Data data, boolean isConvertMeta, boolean isReply, boolean isReplicaSend) throws InvalidKeyException, SignatureException, IOException { Data filteredData = dataFilterTTL.filter(data, isConvertMeta, isReply); filteredData.encodeHeader(buf, signatureFactory); filteredData.encodeBuffer(buf); filteredData.encodeDone(buf, signatureFactory, message.privateKey()); - if(isReply) { + if(isReply || isReplicaSend) { filteredData.release(); } } diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index 14a9306d3..6a9f46000 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -104,8 +104,6 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { - //if exeception is not propagated, we may need to wait for the timeout - //super.exceptionCaught(ctx, cause); if (encoder.message() == null) { LOG.error("Exception in encoding when starting.", cause); cause.printStackTrace(); @@ -113,5 +111,7 @@ public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cau LOG.error("Exception in encoding when started.", cause); cause.printStackTrace(); } + //if exeception is not propagated, we may need to wait for the timeout - check testChangeEntryProtectionKey + super.exceptionCaught(ctx, cause); } } diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 0cc30f83a..d0dd9c219 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -217,27 +217,27 @@ public Map> putAll(final NavigableMap dataMa continue; } - boolean contains = backend.contains(key); - if (contains) { + final Data oldDataGet = backend.get(key); + if (oldDataGet != null) { if(putIfAbsent) { retVal.put(key, PutStatus.FAILED_NOT_ABSENT); newData.release(); continue; } - final Data oldData = backend.get(key); - if(oldData.isDeleted()) { + + if(oldDataGet.isDeleted()) { retVal.put(key, PutStatus.DELETED); newData.release(); continue; } - if(!oldData.basedOnSet().equals(newData.basedOnSet())) { + if(!oldDataGet.basedOnSet().equals(newData.basedOnSet())) { retVal.put(key, PutStatus.VERSION_FORK); newData.release(); continue; } } - Data oldData = backend.put(key, newData); + final Data oldDataPut = backend.put(key, newData); long expiration = newData.expirationMillis(); // handle timeout @@ -248,8 +248,8 @@ public Map> putAll(final NavigableMap dataMa } else { retVal.put(key, PutStatus.OK); } - if(oldData != null && oldData != newData) { - oldData.release(); + if(oldDataPut != null && oldDataPut != newData) { + oldDataPut.release(); } } diff --git a/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java b/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java index e2378fb1c..11157242c 100644 --- a/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java +++ b/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java @@ -344,12 +344,14 @@ public static String getVersionKeysFromMap(Map dataMap) { * The location key. */ private FutureDone synchronizeData(final Number160 locationKey) { - Number640 min = new Number640(locationKey, Number160.ZERO, Number160.ZERO, Number160.ZERO); + return send(locationKey); + } + + private NavigableMap dataMap(final Number160 locationKey) { + Number640 min = new Number640(locationKey, Number160.ZERO, Number160.ZERO, Number160.ZERO); Number640 max = new Number640(locationKey, Number160.MAX_VALUE, Number160.MAX_VALUE, Number160.MAX_VALUE); - final NavigableMap dataMap = peer.storageLayer().get(min, max, -1, true); - return send(locationKey, dataMap); - + return peer.storageLayer().get(min, max, -1, true); } /** @@ -363,7 +365,7 @@ private FutureDone synchronizeData(final Number160 locationKey) { * The data to store * @return The future of the put */ - protected FutureDone send(final Number160 locationKey, final NavigableMap dataMap) { + protected FutureDone send(final Number160 locationKey) { int replicationFactor = replication.replicationFactor() - 1; List closePeers = new ArrayList(); SortedSet sortedSet = peer.peerBean().peerMap() @@ -377,6 +379,8 @@ protected FutureDone send(final Number160 locationKey, final NavigableMap dataMap = dataMap(locationKey); retVal.add(replicationSender.sendDirect(peerStatistic.peerAddress(), locationKey, dataMap)); if (count == replicationFactor) { break; From 90dbf9f610d5451821d7efbb2bc43f44964a2f60 Mon Sep 17 00:00:00 2001 From: tbocek Date: Fri, 19 Jun 2015 21:55:03 +0200 Subject: [PATCH 033/135] Concurrency Bug with Rangelocks. Was very difficult to find this one --- .../main/java/net/tomp2p/dht/RangeLock.java | 75 +++++++++++-- .../java/net/tomp2p/dht/TestRangeLock.java | 103 ++++++++++++++---- .../replication/IndirectReplication.java | 14 +-- 3 files changed, 152 insertions(+), 40 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/RangeLock.java b/dht/src/main/java/net/tomp2p/dht/RangeLock.java index 00bed8616..28d76c7d9 100644 --- a/dht/src/main/java/net/tomp2p/dht/RangeLock.java +++ b/dht/src/main/java/net/tomp2p/dht/RangeLock.java @@ -1,5 +1,7 @@ package net.tomp2p.dht; +import java.util.ArrayList; +import java.util.Collection; import java.util.NavigableMap; import java.util.TreeMap; @@ -22,6 +24,34 @@ public void unlock() { } } + public Range tryLock(final K fromKey, final K toKey) { + final long id = Thread.currentThread().getId(); + synchronized (lockInternal) { + //first check overlappings or smaller subset of keys + final NavigableMap subMap = cache.subMap(fromKey, true, toKey, true); + if (!subMap.isEmpty()) { + if(sizeFiltered(id, subMap) != 0) { + return null; + } + } + + //second check larger subset of keys + final Collection before = cache.headMap(fromKey, false).values(); + final Collection after = cache.tailMap(toKey, false).values(); + //now check for intersection thread ids + final Collection intersection = intersection(before, after); + if(!intersection.isEmpty()) { + if(sizeFiltered(id, intersection) != 0) { + return null; + } + } + + cache.put(fromKey, id); + cache.put(toKey, id); + } + return new Range(fromKey, toKey, this); + } + /** * The same thread can lock a range twice. The first unlock for range x unlocks all range x. * @param fromKey @@ -32,10 +62,16 @@ public Range lock(final K fromKey, final K toKey) { final long id = Thread.currentThread().getId(); synchronized (lockInternal) { final NavigableMap subMap = cache.subMap(fromKey, true, toKey, true); - while (subMap.size() > 0) { - if(mapSizeFiltered(id, subMap) == 0) { + final Collection before = cache.headMap(fromKey, false).values(); + final Collection after = cache.tailMap(toKey, false).values(); + Collection intersection = null; + + while (!subMap.isEmpty() || !(intersection = intersection(before, after)).isEmpty()) { + if((subMap.isEmpty() || sizeFiltered(id, subMap) == 0) && + (intersection.isEmpty() || sizeFiltered(id, intersection) == 0)) { break; } + try { lockInternal.wait(); } catch (InterruptedException e) { @@ -48,15 +84,13 @@ public Range lock(final K fromKey, final K toKey) { } return new Range(fromKey, toKey, this); } - - private int mapSizeFiltered(final long id, final NavigableMap subMap) { - int counter = 0; - for(final long longValue:subMap.values()) { - if(longValue != id) { - counter ++; - } - } - return counter; + + //make a copy! + private Collection intersection(final Collection before, + final Collection after) { + final Collection intersection = new ArrayList(before); + intersection.retainAll(after); + return intersection; } public void unlock(RangeLock.Range lock) { @@ -73,4 +107,23 @@ public int size() { } } + private static int sizeFiltered(final long id, final NavigableMap subMap) { + int counter = 0; + for(final long longValue:subMap.values()) { + if(longValue != id) { + counter ++; + } + } + return counter; + } + + private static int sizeFiltered(final long id, final Collection intersection) { + int counter = 0; + for(final long longValue:intersection) { + if(longValue != id) { + counter ++; + } + } + return counter; + } } diff --git a/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java b/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java index 0c618f28e..a55a3be77 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java +++ b/dht/src/test/java/net/tomp2p/dht/TestRangeLock.java @@ -1,8 +1,10 @@ package net.tomp2p.dht; -import java.util.NavigableMap; -import java.util.TreeMap; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicLong; + +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.Number640; import org.junit.Assert; import org.junit.Rule; @@ -19,41 +21,87 @@ protected void starting(Description description) { System.out.println("Starting test: " + description.getMethodName()); } }; - - @Test + + @Test public void testRangeLockOverlapping() throws InterruptedException { + testRangeLockOverlapping(1, 2, 2, 3); + testRangeLockOverlapping(1, 4, 2, 4); + testRangeLockOverlapping(1, 5, 2, 6); + testRangeLockOverlapping(1, 5, 1, 5); + testRangeLockOverlapping(1, 5, 2, 4); + testRangeLockOverlapping(2, 4, 1, 5); + } + + private void testRangeLockOverlapping(int a1, int a2, int b1, int b2) throws InterruptedException { + testRangeLockOverlapping1(a1, a2, b1, b2); + testRangeLockOverlapping2(a1, a2, b1, b2); + } + + private void testRangeLockOverlapping1(final int a1, final int a2, final int b1, final int b2) throws InterruptedException { + //System.err.println("test1 "+a1 +","+a2+"/"+b1+","+b2); final CountDownLatch cd = new CountDownLatch(1); final RangeLock r = new RangeLock(); - RangeLock.Range lock = r.lock(1, 2); + RangeLock.Range lock = r.lock(a1, a2); Assert.assertEquals(2, r.size()); + final AtomicLong diff = new AtomicLong(); + final long start = System.currentTimeMillis(); new Thread(new Runnable() { @Override public void run() { - RangeLock.Range rr = r.lock(2, 3); + Assert.assertEquals(2, r.size()); + RangeLock.Range rr = r.lock(b1, b2); + diff.set(System.currentTimeMillis() - start); Assert.assertEquals(2, r.size()); r.unlock(rr); Assert.assertEquals(0, r.size()); cd.countDown(); } }).start(); - Thread.sleep(500); + Thread.sleep(50); r.unlock(lock); + cd.await(); + Assert.assertTrue(diff.get() >= 50); + } + + private void testRangeLockOverlapping2(final int a1, final int a2, final int b1, final int b2) throws InterruptedException { + //System.err.println("test2 "+a1 +","+a2+"/"+b1+","+b2); + final CountDownLatch cd = new CountDownLatch(1); + final RangeLock r = new RangeLock(); + RangeLock.Range lock = r.lock(a1, a2); + Assert.assertEquals(2, r.size()); + new Thread(new Runnable() { + @Override + public void run() { + Assert.assertEquals(2, r.size()); + RangeLock.Range lock2 = r.tryLock(b1, b2); + Assert.assertNull(lock2); + Assert.assertEquals(2, r.size()); + cd.countDown(); + } + }).start(); cd.await(); + r.unlock(lock); + Assert.assertEquals(0, r.size()); } + + @Test + public void testRangeLockNonOverlapping() throws InterruptedException { + testRangeLockNonOverlapping(1, 2, 3, 4); + testRangeLockNonOverlapping(3, 4, 1, 2); + } - @Test - public void testRangeLockNonOverlapping() throws InterruptedException { + private void testRangeLockNonOverlapping(final int a1, final int a2, final int b1, final int b2) throws InterruptedException { final CountDownLatch cd = new CountDownLatch(1); final RangeLock r = new RangeLock(); - RangeLock.Range lock = r.lock(1, 2); + RangeLock.Range lock = r.lock(a1, a2); Assert.assertEquals(2, r.size()); new Thread(new Runnable() { @Override public void run() { - RangeLock.Range rr = r.lock(3, 4); + RangeLock.Range rr = r.lock(b1, b2); Assert.assertEquals(4, r.size()); r.unlock(rr); cd.countDown(); @@ -65,18 +113,31 @@ public void run() { } @Test - public void testTreeMap() { - final NavigableMap cache = new TreeMap(); + public void testNumber640() throws InterruptedException { + final CountDownLatch cd = new CountDownLatch(1); + final Number640 gMin = new Number640(new Number160("0x6469ac84a89748bb67b923c833ed0c778a17aea3"), new Number160("0x0"), new Number160("0x0"), new Number160("0x0")); + final Number640 gMax = new Number640(new Number160("0x6469ac84a89748bb67b923c833ed0c778a17aea3"), new Number160("0xffffffffffffffffffffffffffffffffffffffff"), new Number160("0xffffffffffffffffffffffffffffffffffffffff"), new Number160("0xffffffffffffffffffffffffffffffffffffffff")); + + final Number640 pMin = new Number640(new Number160("0x6469ac84a89748bb67b923c833ed0c778a17aea3"), new Number160("0x9120580e94f134cb7c9f27cd1e43dbc82980e152"), new Number160("0x40f06fd774092478d450774f5ba30c5da78acc8"), new Number160("0x2579476ab7f8486700000000")); + final Number640 pMax = new Number640(new Number160("0x6469ac84a89748bb67b923c833ed0c778a17aea3"), new Number160("0x9120580e94f134cb7c9f27cd1e43dbc82980e152"), new Number160("0x40f06fd774092478d450774f5ba30c5da78acc8"), new Number160("0xdb630bdf5d05a8bde00000000")); - cache.put(10, 10); - cache.put(20, 20); - cache.put(30, 30); - cache.put(40, 40); + final RangeLock r = new RangeLock(); + + RangeLock.Range lock1 = r.lock(gMin, gMax); + Assert.assertEquals(2, r.size()); - NavigableMap tmp = cache.subMap(20, true, 30, true); - Assert.assertEquals(2, tmp.size()); - tmp.put(25, 25); - Assert.assertEquals(3, tmp.size()); + new Thread(new Runnable() { + @Override + public void run() { + RangeLock.Range lock2 = r.tryLock(pMin, pMax); + Assert.assertNull(lock2); + Assert.assertEquals(2, r.size()); + cd.countDown(); + } + }).start(); + cd.await(); + r.unlock(lock1); + Assert.assertEquals(0, r.size()); } } diff --git a/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java b/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java index 11157242c..70cc5ab8d 100644 --- a/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java +++ b/replication/src/main/java/net/tomp2p/replication/IndirectReplication.java @@ -346,13 +346,6 @@ public static String getVersionKeysFromMap(Map dataMap) { private FutureDone synchronizeData(final Number160 locationKey) { return send(locationKey); } - - private NavigableMap dataMap(final Number160 locationKey) { - Number640 min = new Number640(locationKey, Number160.ZERO, Number160.ZERO, Number160.ZERO); - Number640 max = new Number640(locationKey, Number160.MAX_VALUE, Number160.MAX_VALUE, - Number160.MAX_VALUE); - return peer.storageLayer().get(min, max, -1, true); - } /** * If my peer is responsible, I'll issue a put if absent to make sure all replicas are stored. @@ -380,7 +373,12 @@ protected FutureDone send(final Number160 locationKey) { count++; closePeers.add(peerStatistic.peerAddress()); //this must be inside the loop as we need to retain the data for every peer - final NavigableMap dataMap = dataMap(locationKey); + + Number640 min = new Number640(locationKey, Number160.ZERO, Number160.ZERO, Number160.ZERO); + Number640 max = new Number640(locationKey, Number160.MAX_VALUE, Number160.MAX_VALUE, + Number160.MAX_VALUE); + final NavigableMap dataMap = peer.storageLayer().get(min, max, -1, true); + retVal.add(replicationSender.sendDirect(peerStatistic.peerAddress(), locationKey, dataMap)); if (count == replicationFactor) { break; From e948b72b0f17fe4a38eeeee107d27b674e1c47db Mon Sep 17 00:00:00 2001 From: tbocek Date: Fri, 19 Jun 2015 22:14:12 +0200 Subject: [PATCH 034/135] removed android dependency --- nat/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/nat/pom.xml b/nat/pom.xml index cf1300e64..be7bf001e 100644 --- a/nat/pom.xml +++ b/nat/pom.xml @@ -62,13 +62,6 @@ test - - - com.ganyo - gcm-server - 1.0.2 - - junit From 3ae47d2cfe107016865b84082e746f3ddfd3dea4 Mon Sep 17 00:00:00 2001 From: tbocek Date: Fri, 19 Jun 2015 22:14:35 +0200 Subject: [PATCH 035/135] update weupnp --- nat/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/pom.xml b/nat/pom.xml index be7bf001e..33a7adc6d 100644 --- a/nat/pom.xml +++ b/nat/pom.xml @@ -46,7 +46,7 @@ org.bitlet weupnp - 0.1.2 + 0.1.3 From b3e552aa6863a129ee02f31a8badb0253b6e05d9 Mon Sep 17 00:00:00 2001 From: tbocek Date: Fri, 19 Jun 2015 22:15:52 +0200 Subject: [PATCH 036/135] moved manual tests to separate package --- .../java/net/tomp2p/holep/{ => manual}/LocalNATUtils.java | 2 +- .../test/java/net/tomp2p/holep/{ => manual}/TestNATLocal.java | 2 +- .../net/tomp2p/holep/{ => manual}/TestNATTypeDetection.java | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) rename nat/src/test/java/net/tomp2p/holep/{ => manual}/LocalNATUtils.java (99%) rename nat/src/test/java/net/tomp2p/holep/{ => manual}/TestNATLocal.java (99%) rename nat/src/test/java/net/tomp2p/holep/{ => manual}/TestNATTypeDetection.java (97%) diff --git a/nat/src/test/java/net/tomp2p/holep/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java similarity index 99% rename from nat/src/test/java/net/tomp2p/holep/LocalNATUtils.java rename to nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index b5d6d086e..eb7a9de7e 100644 --- a/nat/src/test/java/net/tomp2p/holep/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -1,4 +1,4 @@ -package net.tomp2p.holep; +package net.tomp2p.holep.manual; import java.io.BufferedReader; import java.io.File; diff --git a/nat/src/test/java/net/tomp2p/holep/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java similarity index 99% rename from nat/src/test/java/net/tomp2p/holep/TestNATLocal.java rename to nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 9f3b4a20c..59d61eca2 100644 --- a/nat/src/test/java/net/tomp2p/holep/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -1,4 +1,4 @@ -package net.tomp2p.holep; +package net.tomp2p.holep.manual; import java.io.IOException; import java.net.InetAddress; diff --git a/nat/src/test/java/net/tomp2p/holep/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java similarity index 97% rename from nat/src/test/java/net/tomp2p/holep/TestNATTypeDetection.java rename to nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index 8163529d3..6ded7131b 100644 --- a/nat/src/test/java/net/tomp2p/holep/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -1,4 +1,4 @@ -package net.tomp2p.holep; +package net.tomp2p.holep.manual; import java.io.IOException; import java.net.InetAddress; @@ -6,6 +6,8 @@ import net.tomp2p.connection.Bindings; import net.tomp2p.futures.FutureDone; +import net.tomp2p.holep.NATType; +import net.tomp2p.holep.NATTypeDetection; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; From 07f5457646de69bc9a5b29af42851fbe6d5b0a27 Mon Sep 17 00:00:00 2001 From: tbocek Date: Fri, 19 Jun 2015 22:47:26 +0200 Subject: [PATCH 037/135] intersection needs always to be called, otherwise it will be null --- dht/src/main/java/net/tomp2p/dht/RangeLock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dht/src/main/java/net/tomp2p/dht/RangeLock.java b/dht/src/main/java/net/tomp2p/dht/RangeLock.java index 28d76c7d9..abadb4538 100644 --- a/dht/src/main/java/net/tomp2p/dht/RangeLock.java +++ b/dht/src/main/java/net/tomp2p/dht/RangeLock.java @@ -66,7 +66,7 @@ public Range lock(final K fromKey, final K toKey) { final Collection after = cache.tailMap(toKey, false).values(); Collection intersection = null; - while (!subMap.isEmpty() || !(intersection = intersection(before, after)).isEmpty()) { + while (!(intersection = intersection(before, after)).isEmpty() || !subMap.isEmpty()) { if((subMap.isEmpty() || sizeFiltered(id, subMap) == 0) && (intersection.isEmpty() || sizeFiltered(id, intersection) == 0)) { break; From 88ba47691243a3202a2d844b19463b3ae1fb0209 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 24 Jun 2015 17:09:59 +0200 Subject: [PATCH 038/135] not requiered to make copy, causes ConcurrentModificationException --- dht/src/main/java/net/tomp2p/dht/StorageLayer.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index d0dd9c219..676f32fbd 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -795,11 +795,7 @@ public Collection findContentForResponsiblePeerID(Number160 peerID) { RangeLock.Range lockResp = lockResponsibility(peerID); try { Collection contentIDs = backend.findContentForResponsiblePeerID(peerID); - if (contentIDs == null) { - return Collections. emptyList(); - } else { - return new ArrayList(contentIDs); - } + return contentIDs == null ? Collections. emptyList() : contentIDs; } finally { lockResp.unlock(); } From 814f63f37cf0f58b0aee63d203132b6481e22026 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 24 Jun 2015 21:23:08 +0200 Subject: [PATCH 039/135] Added IPC via sysout/command line arguments to send code to execute in an other Java process --- .../java/net/tomp2p/holep/manual/Command.java | 26 +++ .../tomp2p/holep/manual/LocalNATUtils.java | 150 ++++++++++---- .../net/tomp2p/holep/manual/RemotePeer.java | 36 ++++ .../java/net/tomp2p/holep/manual/Result.java | 7 + .../net/tomp2p/holep/manual/TestNATLocal.java | 194 +++++++++--------- .../holep/manual/TestNATTypeDetection.java | 168 ++++++++++----- 6 files changed, 383 insertions(+), 198 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/Command.java create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/Result.java diff --git a/nat/src/test/java/net/tomp2p/holep/manual/Command.java b/nat/src/test/java/net/tomp2p/holep/manual/Command.java new file mode 100644 index 000000000..6dc89e0e6 --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/Command.java @@ -0,0 +1,26 @@ +package net.tomp2p.holep.manual; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public abstract class Command implements Serializable { + + private static final long serialVersionUID = 1L; + private static Map global = new HashMap(); + + public void put(Object key, Object value) { + synchronized (global) { + global.put(key, value); + } + + } + + public Object get(Object key) { + synchronized (global) { + return global.get(key); + } + } + + public abstract Serializable execute() throws Exception; +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index eb7a9de7e..53e48c6a1 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -1,11 +1,18 @@ package net.tomp2p.holep.manual; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.PrintWriter; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Base64; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReferenceArray; import net.tomp2p.connection.Bindings; import net.tomp2p.p2p.Peer; @@ -13,14 +20,17 @@ import net.tomp2p.peers.Number160; public class LocalNATUtils { - public static int executeNatSetup(String action, String... cmd) throws IOException, InterruptedException { + private static final String TAG = "##BASE64##:"; + + public static int executeNatSetup(String action, String... cmd) + throws IOException, InterruptedException { String startDir = System.getProperty("user.dir"); String[] cmds = new String[cmd.length + 3]; cmds[0] = "/usr/bin/sudo"; - cmds[1] = startDir+"/src/test/resources/nat-net.sh"; + cmds[1] = startDir + "/src/test/resources/nat-net.sh"; cmds[2] = action; - for(int i=3;i klass, String nr, String... cmd) throws IOException, InterruptedException { + public static RemotePeer executePeer(Class klass, String nr, final Command... cmd) + throws IOException, InterruptedException, ClassNotFoundException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator - + "java"; + + "java"; String classpath = System.getProperty("java.class.path"); String className = klass.getCanonicalName(); - String[] cmds = new String[cmd.length + 10]; + final String[] cmds = new String[cmd.length + 10]; cmds[0] = "sudo"; cmds[1] = "ip"; cmds[2] = "netns"; @@ -47,66 +58,117 @@ public static Process executePeer(Class klass, String nr, String... cmd) thro cmds[7] = classpath; cmds[8] = className; cmds[9] = nr; - for(int i=10;i results = new AtomicReferenceArray(cmd.length); + new Thread(new Runnable() { + @Override + public void run() { + try { + for (int i = 0; i < cmd.length; i++) { + boolean done = false; + while (!done) { + String line = read(process.getInputStream()).trim(); + if (line.startsWith(TAG)) { + line = line.substring(TAG.length()); + System.out.println("from : " + line); + Object o = fromString(line); + results.set(i, o); + done = true; + } else { + System.out.println("from remote: " + line); + } + } + cl.countDown(); + } + } catch (Throwable t) { + t.printStackTrace(); + } + + } + }).start(); System.err.println("peer started"); - return process; + return new RemotePeer(process, cl, cmd, results); } - public static String waitForLineOrDie(Process process, String prefix, String input) throws IOException { - - // Write to stream - if (input != null) { - PrintWriter pw = new PrintWriter(process.getOutputStream()); - pw.println(input); - pw.flush(); - } - String retVal = read(process.getInputStream(), prefix); - if(retVal == null) { - process.destroy(); - } - return retVal; - } - - public static String read(InputStream is, String prefix) throws IOException { + public static String read(InputStream is) throws IOException { // Read out dir output InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); - String line; - - while ((line = br.readLine()) != null) { - if (line.trim().startsWith(prefix)) { - String retVal = line.substring(prefix.length()).trim(); - System.err.println("found: "+prefix+" -> "+retVal); - return retVal; - } - } - System.err.println("no inputstream"); - return null; + return br.readLine(); } - public static int killPeer(Process process) throws InterruptedException, IOException { + public static int killPeer(Process process) throws InterruptedException, + IOException { process.destroy(); process.getErrorStream().close(); process.getInputStream().close(); process.getOutputStream().close(); return process.waitFor(); } - + /** * As set in: tomp2p/nat/src/test/resources/nat-net.sh */ - public static Peer createRealNode(Number160 relayPeerId, String iface) throws Exception { + public static Peer createRealNode(Number160 relayPeerId, String iface) + throws Exception { // relay Bindings b2 = new Bindings(); b2.addInterface(iface); return new PeerBuilder(relayPeerId).ports(5002).bindings(b2).start(); } + + /** + * As seen in: http://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string + */ + public static Object fromString(String s) throws IOException, + ClassNotFoundException { + byte[] data = Base64.getDecoder().decode(s); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream( + data)); + Object o = ois.readObject(); + ois.close(); + return o; + } + + /** + * As seen in: http://stackoverflow.com/questions/134492/how-to-serialize-an-object-into-a-string + */ + /** Write the object to a Base64 string. */ + public static String toString(Serializable o) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(o); + oos.close(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + + public static Command[] toObjects(String[] args) throws ClassNotFoundException, IOException { + Command[] cmd = new Command[args.length-1]; + for(int i=1;i results; + public RemotePeer(Process process, CountDownLatch cl, Command[] cmd, + AtomicReferenceArray results) { + this.process = process; + this.cl = cl; + this.cmd = cmd; + this.results = results; + } + public Process process() { + return process; + } + public void waitFor() { + try { + cl.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + public Object getResult(int i) { + return results.get(i); + } + public Command getCmd(int i) { + return cmd[i]; + } + +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/Result.java b/nat/src/test/java/net/tomp2p/holep/manual/Result.java new file mode 100644 index 000000000..135dd8014 --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/Result.java @@ -0,0 +1,7 @@ +package net.tomp2p.holep.manual; + +import java.io.Serializable; + +public interface Result extends Serializable { + void result(Object result); +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 59d61eca2..a9827cfcf 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -55,106 +55,106 @@ public void after() throws IOException, InterruptedException { * If you have a terrible lag in InetAddress.getLocalHost(), make sure the hostname resolves in the other network domain. * @throws InterruptedException */ - public static void main(String[] args) throws IOException, InterruptedException { - Peer peer = null; - System.err.println("started on " +InetAddress.getLocalHost()); - try { - Bindings b0 = new Bindings(); - int nr = Integer.parseInt(args[0]); - int ip = Integer.parseInt(args[2]); - Random rnd = new Random(ip); - InetAddress inet = InetAddress.getByName("10.0." + nr + "." + ip); - b0.addAddress(inet); - ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); - ccc.senderTCP(inet); - ccc.senderUDP(inet); - peer = new PeerBuilder(new Number160(rnd)).ports(4000+ip).channelClientConfiguration(ccc).bindings(b0).start(); - System.out.println("started " + peer.peerID()); - System.err.println("started " + peer.peerID()); - String command = LocalNATUtils.read(System.in, "command"); - - while(command!=null && !command.equals("quit")) { - if (command.equals("announce")) { - - FutureAnnounce res; - res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); - res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); - - Thread.sleep(3000); - res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); - res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); - int size = peer.peerBean().localMap().size(); - - - System.err.println("bootstrap to "+ args[1]); - PeerAddress relayP = new PeerAddress(relayPeerId, args[1], 5002, 5002); - peer.bootstrap().peerAddress(relayP).start().awaitUninterruptibly(); - Thread.sleep(2000); - - System.out.println("done " + size); - - - } else if(command.startsWith("ping")) { - String pingNr = command.split(" ")[1]; - String pingIp = command.split(" ")[2]; - Random rnd1 = new Random(Integer.parseInt(pingIp)); - InetAddress pingInet = InetAddress.getByName("10.0." + pingNr + "." + pingIp); - Number160 ping160 = new Number160(rnd1); - PeerAddress pa = new PeerAddress(ping160, pingInet, 4000+Integer.parseInt(pingIp), 4000+Integer.parseInt(pingIp)); - FuturePing fp = peer.ping().peerAddress(pa).start().awaitUninterruptibly(); - System.out.println("done "+fp.remotePeer().inetAddress()); - } - else { - System.out.println("empty"); - } - command = LocalNATUtils.read(System.in, "command"); - } - System.out.println("done"); - - } finally { - System.out.println("finish"); - if(peer != null) { - peer.shutdown().awaitUninterruptibly(); - } - } - } +// public static void main(String[] args) throws IOException, InterruptedException { +// Peer peer = null; +// System.err.println("started on " +InetAddress.getLocalHost()); +// try { +// Bindings b0 = new Bindings(); +// int nr = Integer.parseInt(args[0]); +// int ip = Integer.parseInt(args[2]); +// Random rnd = new Random(ip); +// InetAddress inet = InetAddress.getByName("10.0." + nr + "." + ip); +// b0.addAddress(inet); +// ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); +// ccc.senderTCP(inet); +// ccc.senderUDP(inet); +// peer = new PeerBuilder(new Number160(rnd)).ports(4000+ip).channelClientConfiguration(ccc).bindings(b0).start(); +// System.out.println("started " + peer.peerID()); +// System.err.println("started " + peer.peerID()); +// String command = LocalNATUtils.read(System.in, "command"); +// +// while(command!=null && !command.equals("quit")) { +// if (command.equals("announce")) { +// +// FutureAnnounce res; +// res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); +// res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); +// +// Thread.sleep(3000); +// res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); +// res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); +// int size = peer.peerBean().localMap().size(); +// +// +// System.err.println("bootstrap to "+ args[1]); +// PeerAddress relayP = new PeerAddress(relayPeerId, args[1], 5002, 5002); +// peer.bootstrap().peerAddress(relayP).start().awaitUninterruptibly(); +// Thread.sleep(2000); +// +// System.out.println("done " + size); +// +// +// } else if(command.startsWith("ping")) { +// String pingNr = command.split(" ")[1]; +// String pingIp = command.split(" ")[2]; +// Random rnd1 = new Random(Integer.parseInt(pingIp)); +// InetAddress pingInet = InetAddress.getByName("10.0." + pingNr + "." + pingIp); +// Number160 ping160 = new Number160(rnd1); +// PeerAddress pa = new PeerAddress(ping160, pingInet, 4000+Integer.parseInt(pingIp), 4000+Integer.parseInt(pingIp)); +// FuturePing fp = peer.ping().peerAddress(pa).start().awaitUninterruptibly(); +// System.out.println("done "+fp.remotePeer().inetAddress()); +// } +// else { +// System.out.println("empty"); +// } +// command = LocalNATUtils.read(System.in, "command"); +// } +// System.out.println("done"); +// +// } finally { +// System.out.println("finish"); +// if(peer != null) { +// peer.shutdown().awaitUninterruptibly(); +// } +// } +// } @Test public void testLocal() throws Exception { - relayPeer = null; - Process unr1 = null; - Process unr2 = null; - try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, "eth1"); - InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); - unr1 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "2"); - unr2 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "3"); - String result1 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command announce"); - String result2 = LocalNATUtils.waitForLineOrDie(unr2, "done", "command announce"); - // - - Assert.assertEquals("1", result1); - Assert.assertEquals("1", result2); - - String result3 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command ping 0 3"); - Assert.assertEquals("/10.0.0.3", result3); - - - } finally { - System.err.print("shutdown."); - if (relayPeer != null) { - relayPeer.shutdown().awaitUninterruptibly(); - relayPeer = null; - } - System.err.print("."); - if (unr1 != null) { - LocalNATUtils.killPeer(unr1); - } - System.err.println("."); - if (unr2 != null) { - LocalNATUtils.killPeer(unr2); - } - } +// relayPeer = null; +// Process unr1 = null; +// Process unr2 = null; +// try { +// relayPeer = LocalNATUtils.createRealNode(relayPeerId, "eth1"); +// InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); +// unr1 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "2"); +// unr2 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "3"); +// String result1 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command announce"); +// String result2 = LocalNATUtils.waitForLineOrDie(unr2, "done", "command announce"); +// // +// +// Assert.assertEquals("1", result1); +// Assert.assertEquals("1", result2); +// +// String result3 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command ping 0 3"); +// Assert.assertEquals("/10.0.0.3", result3); +// +// +// } finally { +// System.err.print("shutdown."); +// if (relayPeer != null) { +// relayPeer.shutdown().awaitUninterruptibly(); +// relayPeer = null; +// } +// System.err.print("."); +// if (unr1 != null) { +// LocalNATUtils.killPeer(unr1); +// } +// System.err.println("."); +// if (unr2 != null) { +// LocalNATUtils.killPeer(unr2); +// } +// } } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index 6ded7131b..392674ab4 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -1,7 +1,9 @@ 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 net.tomp2p.connection.Bindings; @@ -20,25 +22,30 @@ import org.junit.Test; /** - * Add the following lines to sudoers - * username ALL=(ALL) NOPASSWD: /nat-net.sh - * username ALL=(ALL) NOPASSWD: /usr/bin/ip + * Add the following lines to sudoers username ALL=(ALL) NOPASSWD: + * /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. + * 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. + * 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 * */ @Ignore -public class TestNATTypeDetection { +public class TestNATTypeDetection implements Serializable { + + private static final long serialVersionUID = 1L; final static private Random RND = new Random(42); + final static private String INF = "wlp3s0"; static private Peer relayPeer = null; static private Number160 relayPeerId = new Number160(RND); - + @Before public void before() throws IOException, InterruptedException { LocalNATUtils.executeNatSetup("start", "0"); @@ -51,60 +58,109 @@ public void after() throws IOException, InterruptedException { LocalNATUtils.executeNatSetup("stop", "1"); } - - /** - * If you have a terrible lag in InetAddress.getLocalHost(), make sure the hostname resolves in the other network domain. + * If you have a terrible lag in InetAddress.getLocalHost(), make sure the + * hostname resolves in the other network domain. + * + * @throws ClassNotFoundException */ - public static void main(String[] args) throws IOException { - Peer peer = null; - System.err.println("started on " +InetAddress.getLocalHost()); - try { - Bindings b0 = new Bindings(); - int nr = Integer.parseInt(args[0]); - Random rnd = new Random(args[0].hashCode()); - b0.addAddress(InetAddress.getByName("10.0." + args[0] + ".2")); - peer = new PeerBuilder(new Number160(rnd)).ports(nr + 5000).bindings(b0).start(); - System.out.println("started " + peer.peerID()); - System.err.println("started " + peer.peerID()); - String command = LocalNATUtils.read(System.in, "command"); - if (command.equals("detect")) { - System.err.println("connect to relay at "+ args[1]); - PeerAddress relayP = new PeerAddress(relayPeerId, args[1], 5002, 5002); - FutureDone type = NATTypeDetection.checkNATType(peer, relayP).awaitUninterruptibly(); - System.err.println("done " + type.failedReason()); - if(type.isSuccess()) { - System.out.println("done " + type.object().name()); - } else { - System.out.println("done " + type.failedReason()); - } - } else { - System.out.println("empty"); - } - } finally { - System.out.println("finish"); - if(peer != null) { - peer.shutdown().awaitUninterruptibly(); - } + public static void main(String[] args) throws IOException, + ClassNotFoundException { + LocalNATUtils.handleMain(args); + } + + private static Serializable init(Command command, String ip, int port) + throws UnknownHostException, IOException { + Bindings b = new Bindings(); + Random rnd = new Random(0); + b.addAddress(InetAddress.getByName(ip)); + Peer peer = new PeerBuilder(new Number160(rnd)).ports(port).bindings(b) + .start(); + command.put("peer", peer); + return "initialized " + peer.peerAddress(); + } + + private static Serializable discover(final String address, Peer peer) + throws UnknownHostException { + PeerAddress relayP = new PeerAddress(relayPeerId, address, 5002, 5002); + FutureDone type = NATTypeDetection.checkNATType(peer, relayP) + .awaitUninterruptibly(); + if (type.isSuccess()) { + return type.object().name(); + } else { + return type.failedReason(); + } + } + + private static Serializable shutdown(Peer peer) { + if (peer != null) { + peer.shutdown().awaitUninterruptibly(); } + return "shutdown done"; } @Test public void testDetection() throws Exception { relayPeer = null; - Process unr1 = null; - Process unr2 = null; + RemotePeer unr1 = null; + RemotePeer unr2 = null; try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, "eth1"); + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); - unr1 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "0", relayAddress.getHostAddress()); - unr2 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "1", relayAddress.getHostAddress()); - String result1 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command detect"); - String result2 = LocalNATUtils.waitForLineOrDie(unr2, "done", "command detect"); - - Assert.assertEquals(NATType.PORT_PRESERVING.toString(), result1); - Assert.assertEquals(NATType.NON_PRESERVING_OTHER.toString(), result2); - + final String address = relayAddress.getHostAddress(); + unr1 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "0", + new Command[] { new Command() { + // startup + @Override + public Serializable execute() throws Exception { + return init(this, "10.0.0.2", 5000); + } + }, new Command() { + // detect the NAT type + @Override + public Serializable execute() throws Exception { + Peer peer = (Peer) get("peer"); + return discover(address, peer); + } + }, new Command() { + //shutdown + @Override + public Serializable execute() throws Exception { + Peer peer = (Peer) get("peer"); + return shutdown(peer); + } + } }); + + unr2 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "1", + new Command[] { new Command() { + // startup + @Override + public Serializable execute() throws Exception { + return init(this, "10.0.1.2", 5001); + } + }, new Command() { + // detect the NAT type + @Override + public Serializable execute() throws Exception { + Peer peer = (Peer) get("peer"); + return discover(address, peer); + } + }, new Command() { + //shutdown + @Override + public Serializable execute() throws Exception { + Peer peer = (Peer) get("peer"); + return 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.err.print("shutdown."); if (relayPeer != null) { @@ -113,14 +169,12 @@ public void testDetection() throws Exception { } System.err.print("."); if (unr1 != null) { - LocalNATUtils.killPeer(unr1); + LocalNATUtils.killPeer(unr1.process()); } System.err.println("."); if (unr2 != null) { - LocalNATUtils.killPeer(unr2); + LocalNATUtils.killPeer(unr2.process()); } } } - - } From 5051620c064866fcbe5ecefff8da1b6dfd0c4e2c Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 24 Jun 2015 22:23:09 +0200 Subject: [PATCH 040/135] Base64 backportet for 1.7 --- .../java/net/tomp2p/holep/manual/Base64.java | 1002 +++++++++++++++++ .../tomp2p/holep/manual/LocalNATUtils.java | 1 - 2 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/Base64.java diff --git a/nat/src/test/java/net/tomp2p/holep/manual/Base64.java b/nat/src/test/java/net/tomp2p/holep/manual/Base64.java new file mode 100644 index 000000000..d0122280b --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/Base64.java @@ -0,0 +1,1002 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//Backport to Java 1.7 + +package net.tomp2p.holep.manual; + +import java.io.FilterOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Objects; + +/** + * This class consists exclusively of static methods for obtaining + * encoders and decoders for the Base64 encoding scheme. The + * implementation of this class supports the following types of Base64 + * as specified in + * RFC 4648 and + * RFC 2045. + * + *
    + *
  • Basic + *

    Uses "The Base64 Alphabet" as specified in Table 1 of + * RFC 4648 and RFC 2045 for encoding and decoding operation. + * The encoder does not add any line feed (line separator) + * character. The decoder rejects data that contains characters + * outside the base64 alphabet.

  • + * + *
  • URL and Filename safe + *

    Uses the "URL and Filename safe Base64 Alphabet" as specified + * in Table 2 of RFC 4648 for encoding and decoding. The + * encoder does not add any line feed (line separator) character. + * The decoder rejects data that contains characters outside the + * base64 alphabet.

  • + * + *
  • MIME + *

    Uses the "The Base64 Alphabet" as specified in Table 1 of + * RFC 2045 for encoding and decoding operation. The encoded output + * must be represented in lines of no more than 76 characters each + * and uses a carriage return {@code '\r'} followed immediately by + * a linefeed {@code '\n'} as the line separator. No line separator + * is added to the end of the encoded output. All line separators + * or other characters not found in the base64 alphabet table are + * ignored in decoding operation.

  • + *
+ * + *

Unless otherwise noted, passing a {@code null} argument to a + * method of this class will cause a {@link java.lang.NullPointerException + * NullPointerException} to be thrown. + * + * @author Xueming Shen + * @since 1.8 + */ + +public class Base64 { + + private Base64() {} + + /** + * Returns a {@link Encoder} that encodes using the + * Basic type base64 encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getEncoder() { + return Encoder.RFC4648; + } + + /** + * Returns a {@link Encoder} that encodes using the + * URL and Filename safe type base64 + * encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getUrlEncoder() { + return Encoder.RFC4648_URLSAFE; + } + + /** + * Returns a {@link Encoder} that encodes using the + * MIME type base64 encoding scheme. + * + * @return A Base64 encoder. + */ + public static Encoder getMimeEncoder() { + return Encoder.RFC2045; + } + + /** + * Returns a {@link Encoder} that encodes using the + * MIME type base64 encoding scheme + * with specified line length and line separators. + * + * @param lineLength + * the length of each output line (rounded down to nearest multiple + * of 4). If {@code lineLength <= 0} the output will not be separated + * in lines + * @param lineSeparator + * the line separator for each output line + * + * @return A Base64 encoder. + * + * @throws IllegalArgumentException if {@code lineSeparator} includes any + * character of "The Base64 Alphabet" as specified in Table 1 of + * RFC 2045. + */ + public static Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) { + Objects.requireNonNull(lineSeparator); + int[] base64 = Decoder.fromBase64; + for (byte b : lineSeparator) { + if (base64[b & 0xff] != -1) + throw new IllegalArgumentException( + "Illegal base64 line separator character 0x" + Integer.toString(b, 16)); + } + if (lineLength <= 0) { + return Encoder.RFC4648; + } + return new Encoder(false, lineSeparator, lineLength >> 2 << 2, true); + } + + /** + * Returns a {@link Decoder} that decodes using the + * Basic type base64 encoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getDecoder() { + return Decoder.RFC4648; + } + + /** + * Returns a {@link Decoder} that decodes using the + * URL and Filename safe type base64 + * encoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getUrlDecoder() { + return Decoder.RFC4648_URLSAFE; + } + + /** + * Returns a {@link Decoder} that decodes using the + * MIME type base64 decoding scheme. + * + * @return A Base64 decoder. + */ + public static Decoder getMimeDecoder() { + return Decoder.RFC2045; + } + + /** + * This class implements an encoder for encoding byte data using + * the Base64 encoding scheme as specified in RFC 4648 and RFC 2045. + * + *

Instances of {@link Encoder} class are safe for use by + * multiple concurrent threads. + * + *

Unless otherwise noted, passing a {@code null} argument to + * a method of this class will cause a + * {@link java.lang.NullPointerException NullPointerException} to + * be thrown. + * + * @see Decoder + * @since 1.8 + */ + public static class Encoder { + + private final byte[] newline; + private final int linemax; + private final boolean isURL; + private final boolean doPadding; + + private Encoder(boolean isURL, byte[] newline, int linemax, boolean doPadding) { + this.isURL = isURL; + this.newline = newline; + this.linemax = linemax; + this.doPadding = doPadding; + } + + /** + * This array is a lookup table that translates 6-bit positive integer + * index values into their "Base64 Alphabet" equivalents as specified + * in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648). + */ + private static final char[] toBase64 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + /** + * It's the lookup table for "URL and Filename safe Base64" as specified + * in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and + * '_'. This table is used when BASE64_URL is specified. + */ + private static final char[] toBase64URL = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + private static final int MIMELINEMAX = 76; + private static final byte[] CRLF = new byte[] {'\r', '\n'}; + + static final Encoder RFC4648 = new Encoder(false, null, -1, true); + static final Encoder RFC4648_URLSAFE = new Encoder(true, null, -1, true); + static final Encoder RFC2045 = new Encoder(false, CRLF, MIMELINEMAX, true); + + private final int outLength(int srclen) { + int len = 0; + if (doPadding) { + len = 4 * ((srclen + 2) / 3); + } else { + int n = srclen % 3; + len = 4 * (srclen / 3) + (n == 0 ? 0 : n + 1); + } + if (linemax > 0) // line separators + len += (len - 1) / linemax * newline.length; + return len; + } + + /** + * Encodes all bytes from the specified byte array into a newly-allocated + * byte array using the {@link Base64} encoding scheme. The returned byte + * array is of the length of the resulting bytes. + * + * @param src + * the byte array to encode + * @return A newly-allocated byte array containing the resulting + * encoded bytes. + */ + public byte[] encode(byte[] src) { + int len = outLength(src.length); // dst array size + byte[] dst = new byte[len]; + int ret = encode0(src, 0, src.length, dst); + if (ret != dst.length) + return Arrays.copyOf(dst, ret); + return dst; + } + + /** + * Encodes all bytes from the specified byte array using the + * {@link Base64} encoding scheme, writing the resulting bytes to the + * given output byte array, starting at offset 0. + * + *

It is the responsibility of the invoker of this method to make + * sure the output byte array {@code dst} has enough space for encoding + * all bytes from the input byte array. No bytes will be written to the + * output byte array if the output byte array is not big enough. + * + * @param src + * the byte array to encode + * @param dst + * the output byte array + * @return The number of bytes written to the output byte array + * + * @throws IllegalArgumentException if {@code dst} does not have enough + * space for encoding all input bytes. + */ + public int encode(byte[] src, byte[] dst) { + int len = outLength(src.length); // dst array size + if (dst.length < len) + throw new IllegalArgumentException( + "Output byte array is too small for encoding all input bytes"); + return encode0(src, 0, src.length, dst); + } + + /** + * Encodes the specified byte array into a String using the {@link Base64} + * encoding scheme. + * + *

This method first encodes all input bytes into a base64 encoded + * byte array and then constructs a new String by using the encoded byte + * array and the {@link java.nio.charset.StandardCharsets#ISO_8859_1 + * ISO-8859-1} charset. + * + *

In other words, an invocation of this method has exactly the same + * effect as invoking + * {@code new String(encode(src), StandardCharsets.ISO_8859_1)}. + * + * @param src + * the byte array to encode + * @return A String containing the resulting Base64 encoded characters + */ + @SuppressWarnings("deprecation") + public String encodeToString(byte[] src) { + byte[] encoded = encode(src); + return new String(encoded, 0, 0, encoded.length); + } + + /** + * Encodes all remaining bytes from the specified byte buffer into + * a newly-allocated ByteBuffer using the {@link Base64} encoding + * scheme. + * + * Upon return, the source buffer's position will be updated to + * its limit; its limit will not have been changed. The returned + * output buffer's position will be zero and its limit will be the + * number of resulting encoded bytes. + * + * @param buffer + * the source ByteBuffer to encode + * @return A newly-allocated byte buffer containing the encoded bytes. + */ + public ByteBuffer encode(ByteBuffer buffer) { + int len = outLength(buffer.remaining()); + byte[] dst = new byte[len]; + int ret = 0; + if (buffer.hasArray()) { + ret = encode0(buffer.array(), + buffer.arrayOffset() + buffer.position(), + buffer.arrayOffset() + buffer.limit(), + dst); + buffer.position(buffer.limit()); + } else { + byte[] src = new byte[buffer.remaining()]; + buffer.get(src); + ret = encode0(src, 0, src.length, dst); + } + if (ret != dst.length) + dst = Arrays.copyOf(dst, ret); + return ByteBuffer.wrap(dst); + } + + /** + * Wraps an output stream for encoding byte data using the {@link Base64} + * encoding scheme. + * + *

It is recommended to promptly close the returned output stream after + * use, during which it will flush all possible leftover bytes to the underlying + * output stream. Closing the returned output stream will close the underlying + * output stream. + * + * @param os + * the output stream. + * @return the output stream for encoding the byte data into the + * specified Base64 encoded format + */ + public OutputStream wrap(OutputStream os) { + Objects.requireNonNull(os); + return new EncOutputStream(os, isURL ? toBase64URL : toBase64, + newline, linemax, doPadding); + } + + /** + * Returns an encoder instance that encodes equivalently to this one, + * but without adding any padding character at the end of the encoded + * byte data. + * + *

The encoding scheme of this encoder instance is unaffected by + * this invocation. The returned encoder instance should be used for + * non-padding encoding operation. + * + * @return an equivalent encoder that encodes without adding any + * padding character at the end + */ + public Encoder withoutPadding() { + if (!doPadding) + return this; + return new Encoder(isURL, newline, linemax, false); + } + + private int encode0(byte[] src, int off, int end, byte[] dst) { + char[] base64 = isURL ? toBase64URL : toBase64; + int sp = off; + int slen = (end - off) / 3 * 3; + int sl = off + slen; + if (linemax > 0 && slen > linemax / 4 * 3) + slen = linemax / 4 * 3; + int dp = 0; + while (sp < sl) { + int sl0 = Math.min(sp + slen, sl); + for (int sp0 = sp, dp0 = dp ; sp0 < sl0; ) { + int bits = (src[sp0++] & 0xff) << 16 | + (src[sp0++] & 0xff) << 8 | + (src[sp0++] & 0xff); + dst[dp0++] = (byte)base64[(bits >>> 18) & 0x3f]; + dst[dp0++] = (byte)base64[(bits >>> 12) & 0x3f]; + dst[dp0++] = (byte)base64[(bits >>> 6) & 0x3f]; + dst[dp0++] = (byte)base64[bits & 0x3f]; + } + int dlen = (sl0 - sp) / 3 * 4; + dp += dlen; + sp = sl0; + if (dlen == linemax && sp < end) { + for (byte b : newline){ + dst[dp++] = b; + } + } + } + if (sp < end) { // 1 or 2 leftover bytes + int b0 = src[sp++] & 0xff; + dst[dp++] = (byte)base64[b0 >> 2]; + if (sp == end) { + dst[dp++] = (byte)base64[(b0 << 4) & 0x3f]; + if (doPadding) { + dst[dp++] = '='; + dst[dp++] = '='; + } + } else { + int b1 = src[sp++] & 0xff; + dst[dp++] = (byte)base64[(b0 << 4) & 0x3f | (b1 >> 4)]; + dst[dp++] = (byte)base64[(b1 << 2) & 0x3f]; + if (doPadding) { + dst[dp++] = '='; + } + } + } + return dp; + } + } + + /** + * This class implements a decoder for decoding byte data using the + * Base64 encoding scheme as specified in RFC 4648 and RFC 2045. + * + *

The Base64 padding character {@code '='} is accepted and + * interpreted as the end of the encoded byte data, but is not + * required. So if the final unit of the encoded byte data only has + * two or three Base64 characters (without the corresponding padding + * character(s) padded), they are decoded as if followed by padding + * character(s). If there is a padding character present in the + * final unit, the correct number of padding character(s) must be + * present, otherwise {@code IllegalArgumentException} ( + * {@code IOException} when reading from a Base64 stream) is thrown + * during decoding. + * + *

Instances of {@link Decoder} class are safe for use by + * multiple concurrent threads. + * + *

Unless otherwise noted, passing a {@code null} argument to + * a method of this class will cause a + * {@link java.lang.NullPointerException NullPointerException} to + * be thrown. + * + * @see Encoder + * @since 1.8 + */ + public static class Decoder { + + private final boolean isURL; + private final boolean isMIME; + + private Decoder(boolean isURL, boolean isMIME) { + this.isURL = isURL; + this.isMIME = isMIME; + } + + /** + * Lookup table for decoding unicode characters drawn from the + * "Base64 Alphabet" (as specified in Table 1 of RFC 2045) into + * their 6-bit positive integer equivalents. Characters that + * are not in the Base64 alphabet but fall within the bounds of + * the array are encoded to -1. + * + */ + private static final int[] fromBase64 = new int[256]; + static { + Arrays.fill(fromBase64, -1); + for (int i = 0; i < Encoder.toBase64.length; i++) + fromBase64[Encoder.toBase64[i]] = i; + fromBase64['='] = -2; + } + + /** + * Lookup table for decoding "URL and Filename safe Base64 Alphabet" + * as specified in Table2 of the RFC 4648. + */ + private static final int[] fromBase64URL = new int[256]; + + static { + Arrays.fill(fromBase64URL, -1); + for (int i = 0; i < Encoder.toBase64URL.length; i++) + fromBase64URL[Encoder.toBase64URL[i]] = i; + fromBase64URL['='] = -2; + } + + static final Decoder RFC4648 = new Decoder(false, false); + static final Decoder RFC4648_URLSAFE = new Decoder(true, false); + static final Decoder RFC2045 = new Decoder(false, true); + + /** + * Decodes all bytes from the input byte array using the {@link Base64} + * encoding scheme, writing the results into a newly-allocated output + * byte array. The returned byte array is of the length of the resulting + * bytes. + * + * @param src + * the byte array to decode + * + * @return A newly-allocated byte array containing the decoded bytes. + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme + */ + public byte[] decode(byte[] src) { + byte[] dst = new byte[outLength(src, 0, src.length)]; + int ret = decode0(src, 0, src.length, dst); + if (ret != dst.length) { + dst = Arrays.copyOf(dst, ret); + } + return dst; + } + + /** + * Decodes a Base64 encoded String into a newly-allocated byte array + * using the {@link Base64} encoding scheme. + * + *

An invocation of this method has exactly the same effect as invoking + * {@code decode(src.getBytes(StandardCharsets.ISO_8859_1))} + * + * @param src + * the string to decode + * + * @return A newly-allocated byte array containing the decoded bytes. + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme + */ + public byte[] decode(String src) { + return decode(src.getBytes(StandardCharsets.ISO_8859_1)); + } + + /** + * Decodes all bytes from the input byte array using the {@link Base64} + * encoding scheme, writing the results into the given output byte array, + * starting at offset 0. + * + *

It is the responsibility of the invoker of this method to make + * sure the output byte array {@code dst} has enough space for decoding + * all bytes from the input byte array. No bytes will be be written to + * the output byte array if the output byte array is not big enough. + * + *

If the input byte array is not in valid Base64 encoding scheme + * then some bytes may have been written to the output byte array before + * IllegalargumentException is thrown. + * + * @param src + * the byte array to decode + * @param dst + * the output byte array + * + * @return The number of bytes written to the output byte array + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme, or {@code dst} + * does not have enough space for decoding all input bytes. + */ + public int decode(byte[] src, byte[] dst) { + int len = outLength(src, 0, src.length); + if (dst.length < len) + throw new IllegalArgumentException( + "Output byte array is too small for decoding all input bytes"); + return decode0(src, 0, src.length, dst); + } + + /** + * Decodes all bytes from the input byte buffer using the {@link Base64} + * encoding scheme, writing the results into a newly-allocated ByteBuffer. + * + *

Upon return, the source buffer's position will be updated to + * its limit; its limit will not have been changed. The returned + * output buffer's position will be zero and its limit will be the + * number of resulting decoded bytes + * + *

{@code IllegalArgumentException} is thrown if the input buffer + * is not in valid Base64 encoding scheme. The position of the input + * buffer will not be advanced in this case. + * + * @param buffer + * the ByteBuffer to decode + * + * @return A newly-allocated byte buffer containing the decoded bytes + * + * @throws IllegalArgumentException + * if {@code src} is not in valid Base64 scheme. + */ + public ByteBuffer decode(ByteBuffer buffer) { + int pos0 = buffer.position(); + try { + byte[] src; + int sp, sl; + if (buffer.hasArray()) { + src = buffer.array(); + sp = buffer.arrayOffset() + buffer.position(); + sl = buffer.arrayOffset() + buffer.limit(); + buffer.position(buffer.limit()); + } else { + src = new byte[buffer.remaining()]; + buffer.get(src); + sp = 0; + sl = src.length; + } + byte[] dst = new byte[outLength(src, sp, sl)]; + return ByteBuffer.wrap(dst, 0, decode0(src, sp, sl, dst)); + } catch (IllegalArgumentException iae) { + buffer.position(pos0); + throw iae; + } + } + + /** + * Returns an input stream for decoding {@link Base64} encoded byte stream. + * + *

The {@code read} methods of the returned {@code InputStream} will + * throw {@code IOException} when reading bytes that cannot be decoded. + * + *

Closing the returned input stream will close the underlying + * input stream. + * + * @param is + * the input stream + * + * @return the input stream for decoding the specified Base64 encoded + * byte stream + */ + public InputStream wrap(InputStream is) { + Objects.requireNonNull(is); + return new DecInputStream(is, isURL ? fromBase64URL : fromBase64, isMIME); + } + + private int outLength(byte[] src, int sp, int sl) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int paddings = 0; + int len = sl - sp; + if (len == 0) + return 0; + if (len < 2) { + if (isMIME && base64[0] == -1) + return 0; + throw new IllegalArgumentException( + "Input byte[] should at least have 2 bytes for base64 bytes"); + } + if (isMIME) { + // scan all bytes to fill out all non-alphabet. a performance + // trade-off of pre-scan or Arrays.copyOf + int n = 0; + while (sp < sl) { + int b = src[sp++] & 0xff; + if (b == '=') { + len -= (sl - sp + 1); + break; + } + if ((b = base64[b]) == -1) + n++; + } + len -= n; + } else { + if (src[sl - 1] == '=') { + paddings++; + if (src[sl - 2] == '=') + paddings++; + } + } + if (paddings == 0 && (len & 0x3) != 0) + paddings = 4 - (len & 0x3); + return 3 * ((len + 3) / 4) - paddings; + } + + private int decode0(byte[] src, int sp, int sl, byte[] dst) { + int[] base64 = isURL ? fromBase64URL : fromBase64; + int dp = 0; + int bits = 0; + int shiftto = 18; // pos of first byte of 4-byte atom + while (sp < sl) { + int b = src[sp++] & 0xff; + if ((b = base64[b]) < 0) { + if (b == -2) { // padding byte '=' + // = shiftto==18 unnecessary padding + // x= shiftto==12 a dangling single x + // x to be handled together with non-padding case + // xx= shiftto==6&&sp==sl missing last = + // xx=y shiftto==6 last is not = + if (shiftto == 6 && (sp == sl || src[sp++] != '=') || + shiftto == 18) { + throw new IllegalArgumentException( + "Input byte array has wrong 4-byte ending unit"); + } + break; + } + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IllegalArgumentException( + "Illegal base64 character " + + Integer.toString(src[sp - 1], 16)); + } + bits |= (b << shiftto); + shiftto -= 6; + if (shiftto < 0) { + dst[dp++] = (byte)(bits >> 16); + dst[dp++] = (byte)(bits >> 8); + dst[dp++] = (byte)(bits); + shiftto = 18; + bits = 0; + } + } + // reached end of byte array or hit padding '=' characters. + if (shiftto == 6) { + dst[dp++] = (byte)(bits >> 16); + } else if (shiftto == 0) { + dst[dp++] = (byte)(bits >> 16); + dst[dp++] = (byte)(bits >> 8); + } else if (shiftto == 12) { + // dangling single "x", incorrectly encoded. + throw new IllegalArgumentException( + "Last unit does not have enough valid bits"); + } + // anything left is invalid, if is not MIME. + // if MIME, ignore all non-base64 character + while (sp < sl) { + if (isMIME && base64[src[sp++]] < 0) + continue; + throw new IllegalArgumentException( + "Input byte array has incorrect ending byte at " + sp); + } + return dp; + } + } + + /* + * An output stream for encoding bytes into the Base64. + */ + private static class EncOutputStream extends FilterOutputStream { + + private int leftover = 0; + private int b0, b1, b2; + private boolean closed = false; + + private final char[] base64; // byte->base64 mapping + private final byte[] newline; // line separator, if needed + private final int linemax; + private final boolean doPadding;// whether or not to pad + private int linepos = 0; + + EncOutputStream(OutputStream os, char[] base64, + byte[] newline, int linemax, boolean doPadding) { + super(os); + this.base64 = base64; + this.newline = newline; + this.linemax = linemax; + this.doPadding = doPadding; + } + + @Override + public void write(int b) throws IOException { + byte[] buf = new byte[1]; + buf[0] = (byte)(b & 0xff); + write(buf, 0, 1); + } + + private void checkNewline() throws IOException { + if (linepos == linemax) { + out.write(newline); + linepos = 0; + } + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (closed) + throw new IOException("Stream is closed"); + if (off < 0 || len < 0 || off + len > b.length) + throw new ArrayIndexOutOfBoundsException(); + if (len == 0) + return; + if (leftover != 0) { + if (leftover == 1) { + b1 = b[off++] & 0xff; + len--; + if (len == 0) { + leftover++; + return; + } + } + b2 = b[off++] & 0xff; + len--; + checkNewline(); + out.write(base64[b0 >> 2]); + out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]); + out.write(base64[(b1 << 2) & 0x3f | (b2 >> 6)]); + out.write(base64[b2 & 0x3f]); + linepos += 4; + } + int nBits24 = len / 3; + leftover = len - (nBits24 * 3); + while (nBits24-- > 0) { + checkNewline(); + int bits = (b[off++] & 0xff) << 16 | + (b[off++] & 0xff) << 8 | + (b[off++] & 0xff); + out.write(base64[(bits >>> 18) & 0x3f]); + out.write(base64[(bits >>> 12) & 0x3f]); + out.write(base64[(bits >>> 6) & 0x3f]); + out.write(base64[bits & 0x3f]); + linepos += 4; + } + if (leftover == 1) { + b0 = b[off++] & 0xff; + } else if (leftover == 2) { + b0 = b[off++] & 0xff; + b1 = b[off++] & 0xff; + } + } + + @Override + public void close() throws IOException { + if (!closed) { + closed = true; + if (leftover == 1) { + checkNewline(); + out.write(base64[b0 >> 2]); + out.write(base64[(b0 << 4) & 0x3f]); + if (doPadding) { + out.write('='); + out.write('='); + } + } else if (leftover == 2) { + checkNewline(); + out.write(base64[b0 >> 2]); + out.write(base64[(b0 << 4) & 0x3f | (b1 >> 4)]); + out.write(base64[(b1 << 2) & 0x3f]); + if (doPadding) { + out.write('='); + } + } + leftover = 0; + out.close(); + } + } + } + + /* + * An input stream for decoding Base64 bytes + */ + private static class DecInputStream extends InputStream { + + private final InputStream is; + private final boolean isMIME; + private final int[] base64; // base64 -> byte mapping + private int bits = 0; // 24-bit buffer for decoding + private int nextin = 18; // next available "off" in "bits" for input; + // -> 18, 12, 6, 0 + private int nextout = -8; // next available "off" in "bits" for output; + // -> 8, 0, -8 (no byte for output) + private boolean eof = false; + private boolean closed = false; + + DecInputStream(InputStream is, int[] base64, boolean isMIME) { + this.is = is; + this.base64 = base64; + this.isMIME = isMIME; + } + + private byte[] sbBuf = new byte[1]; + + @Override + public int read() throws IOException { + return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (closed) + throw new IOException("Stream is closed"); + if (eof && nextout < 0) // eof and no leftover + return -1; + if (off < 0 || len < 0 || len > b.length - off) + throw new IndexOutOfBoundsException(); + int oldOff = off; + if (nextout >= 0) { // leftover output byte(s) in bits buf + do { + if (len == 0) + return off - oldOff; + b[off++] = (byte)(bits >> nextout); + len--; + nextout -= 8; + } while (nextout >= 0); + bits = 0; + } + while (len > 0) { + int v = is.read(); + if (v == -1) { + eof = true; + if (nextin != 18) { + if (nextin == 12) + throw new IOException("Base64 stream has one un-decoded dangling byte."); + // treat ending xx/xxx without padding character legal. + // same logic as v == '=' below + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + } + if (off == oldOff) + return -1; + else + return off - oldOff; + } + if (v == '=') { // padding byte(s) + // = shiftto==18 unnecessary padding + // x= shiftto==12 dangling x, invalid unit + // xx= shiftto==6 && missing last '=' + // xx=y or last is not '=' + if (nextin == 18 || nextin == 12 || + nextin == 6 && is.read() != '=') { + throw new IOException("Illegal base64 ending sequence:" + nextin); + } + b[off++] = (byte)(bits >> (16)); + len--; + if (nextin == 0) { // only one padding byte + if (len == 0) { // no enough output space + bits >>= 8; // shift to lowest byte + nextout = 0; + } else { + b[off++] = (byte) (bits >> 8); + } + } + eof = true; + break; + } + if ((v = base64[v]) == -1) { + if (isMIME) // skip if for rfc2045 + continue; + else + throw new IOException("Illegal base64 character " + + Integer.toString(v, 16)); + } + bits |= (v << nextin); + if (nextin == 0) { + nextin = 18; // clear for next + nextout = 16; + while (nextout >= 0) { + b[off++] = (byte)(bits >> nextout); + len--; + nextout -= 8; + if (len == 0 && nextout >= 0) { // don't clean "bits" + return off - oldOff; + } + } + bits = 0; + } else { + nextin -= 6; + } + } + return off - oldOff; + } + + @Override + public int available() throws IOException { + if (closed) + throw new IOException("Stream is closed"); + return is.available(); // TBD: + } + + @Override + public void close() throws IOException { + if (!closed) { + closed = true; + is.close(); + } + } + } +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 53e48c6a1..b020973ec 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -10,7 +10,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.Base64; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReferenceArray; From b0f951ab3fc8b84ab5b1947e4d62ad7dfe549b86 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 25 Jun 2015 17:49:20 +0200 Subject: [PATCH 041/135] add proper tostring to easy debugging --- core/src/main/java/net/tomp2p/connection/Ports.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/net/tomp2p/connection/Ports.java b/core/src/main/java/net/tomp2p/connection/Ports.java index d3e2af545..f350cc65d 100644 --- a/core/src/main/java/net/tomp2p/connection/Ports.java +++ b/core/src/main/java/net/tomp2p/connection/Ports.java @@ -83,4 +83,11 @@ public boolean isManualPort() { // a manual port-forwarding. return !randomPorts; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("ports(u"); + sb.append(udpPort).append(",t").append(tcpPort).append(")"); + return sb.toString(); + } } From e112dc7fa21b2c927e8b2636fb678515acac231b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 25 Jun 2015 17:50:08 +0200 Subject: [PATCH 042/135] added convenince method --- .../main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 0ec886ca7..d2c10b762 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -34,6 +34,7 @@ import net.tomp2p.p2p.PeerReachable; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.utils.Utils; import org.slf4j.Logger; @@ -88,6 +89,13 @@ public DiscoverBuilder inetSocketAddress(InetAddress inetAddress, int portTCP, i this.portUDP = portUDP; return this; } + + public DiscoverBuilder peerSocketAddress(PeerSocketAddress peerSocketAddress) { + this.inetAddress = peerSocketAddress.inetAddress(); + this.portTCP = peerSocketAddress.tcpPort(); + this.portUDP = peerSocketAddress.udpPort(); + return this; + } public int portUDP() { return portUDP; From 2c2708b99b2c2783e9c78dacd5ec4d3846db9ca6 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 25 Jun 2015 17:50:36 +0200 Subject: [PATCH 043/135] typo --- nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java index 1b2fe1dca..1e885c729 100644 --- a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java +++ b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java @@ -67,7 +67,7 @@ public void operationComplete(FutureChannelCreator future) throws Exception { public void operationComplete(FutureDone future) throws Exception { if (future.isSuccess()) { if (future.object().length != 3) { - futureDone.failed("expected exactly two futures"); + futureDone.failed("expected exactly three futures"); return; } if (!checkCompleteMessage(future.object()[0])) { From 92918f0c74597b44917b26543e8a95cc6a755848 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 25 Jun 2015 17:51:59 +0200 Subject: [PATCH 044/135] improved testcases --- .../tomp2p/holep/manual/LocalNATUtils.java | 99 ++++++++++-- .../net/tomp2p/holep/manual/TestNATLocal.java | 148 +++++++++--------- .../holep/manual/TestNATTypeDetection.java | 81 +++------- nat/src/test/resources/nat-net.sh | 30 +++- 4 files changed, 216 insertions(+), 142 deletions(-) diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index b020973ec..a201fe7de 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -10,16 +10,30 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReferenceArray; import net.tomp2p.connection.Bindings; +import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; public class LocalNATUtils { private static final String TAG = "##BASE64##:"; + + /** + * If you have a terrible lag in InetAddress.getLocalHost(), make sure the + * hostname resolves in the other network domain. + * + * @throws ClassNotFoundException + */ + public static void main(String[] args) throws IOException, + ClassNotFoundException { + LocalNATUtils.handleMain(args); + } public static int executeNatSetup(String action, String... cmd) throws IOException, InterruptedException { @@ -32,13 +46,20 @@ public static int executeNatSetup(String action, String... cmd) cmds[i] = cmd[i - 3]; } final ProcessBuilder builder = new ProcessBuilder(cmds); - builder.redirectError(ProcessBuilder.Redirect.INHERIT); + Process process = builder.start(); + new StreamGobbler(process.getErrorStream(), "ERR_SETUP["+cmd[0]+"]").start(); + new StreamGobbler(process.getInputStream(), "OUT_SETUP["+cmd[0]+"]").start(); process.waitFor(); return process.exitValue(); } + + public static RemotePeer executePeer(int nr, final Command... cmd) + throws IOException, InterruptedException, ClassNotFoundException { + return executePeer(LocalNATUtils.class, nr, cmd); + } - public static RemotePeer executePeer(Class klass, String nr, final Command... cmd) + public static RemotePeer executePeer(Class klass, final int nr, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator @@ -56,15 +77,14 @@ public static RemotePeer executePeer(Class klass, String nr, final Command... cmds[6] = "-cp"; cmds[7] = classpath; cmds[8] = className; - cmds[9] = nr; + cmds[9] = ""+nr; for (int i = 10; i < cmds.length; i++) { cmds[i] = toString(cmd[i - 10]); } ProcessBuilder builder = new ProcessBuilder(cmds); - builder.redirectError(ProcessBuilder.Redirect.INHERIT); final Process process = builder.start(); - System.err.println("executed."); + new StreamGobbler(process.getErrorStream(), "ERR["+nr+"]").start(); final CountDownLatch cl = new CountDownLatch(cmd.length); final AtomicReferenceArray results = new AtomicReferenceArray(cmd.length); new Thread(new Runnable() { @@ -77,12 +97,11 @@ public void run() { String line = read(process.getInputStream()).trim(); if (line.startsWith(TAG)) { line = line.substring(TAG.length()); - System.out.println("from : " + line); Object o = fromString(line); results.set(i, o); done = true; } else { - System.out.println("from remote: " + line); + System.out.println("OUT["+nr+"]>" + line); } } cl.countDown(); @@ -93,7 +112,7 @@ public void run() { } }).start(); - System.err.println("peer started"); + System.out.println("LOCAL> remote peer "+nr+" started"); return new RemotePeer(process, cl, cmd, results); } @@ -152,7 +171,6 @@ public static String toString(Serializable o) throws IOException { public static Command[] toObjects(String[] args) throws ClassNotFoundException, IOException { Command[] cmd = new Command[args.length-1]; for(int i=1;i " + line); + } + } + catch (IOException ioe) { + ioe.printStackTrace(); + } + } + } } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index a9827cfcf..df8b877a2 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -1,17 +1,23 @@ package net.tomp2p.holep.manual; import java.io.IOException; +import java.io.Serializable; import java.net.InetAddress; import java.util.Random; import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.futures.FutureAnnounce; +import net.tomp2p.futures.FutureDiscover; import net.tomp2p.futures.FuturePing; +import net.tomp2p.nat.FutureNAT; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; import org.junit.After; import org.junit.Assert; @@ -33,91 +39,89 @@ * @author Thomas Bocek * */ -@Ignore -public class TestNATLocal { +//@Ignore +public class TestNATLocal implements Serializable { + + private static final long serialVersionUID = 1L; + + //### CHANGE THIS TO YOUR INTERFACE### + final static private String INF = "enp0s25"; + final static private Random RND = new Random(42); static private Peer relayPeer = null; static private Number160 relayPeerId = new Number160(RND); @Before public void before() throws IOException, InterruptedException { - LocalNATUtils.executeNatSetup("start", "0", "sym"); + LocalNATUtils.executeNatSetup("start", "0"); + LocalNATUtils.executeNatSetup("upnp", "0"); } @After public void after() throws IOException, InterruptedException { - LocalNATUtils.executeNatSetup("stop", "0"); + //LocalNATUtils.executeNatSetup("stop", "0"); } - - /** - * If you have a terrible lag in InetAddress.getLocalHost(), make sure the hostname resolves in the other network domain. - * @throws InterruptedException - */ -// public static void main(String[] args) throws IOException, InterruptedException { -// Peer peer = null; -// System.err.println("started on " +InetAddress.getLocalHost()); -// try { -// Bindings b0 = new Bindings(); -// int nr = Integer.parseInt(args[0]); -// int ip = Integer.parseInt(args[2]); -// Random rnd = new Random(ip); -// InetAddress inet = InetAddress.getByName("10.0." + nr + "." + ip); -// b0.addAddress(inet); -// ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); -// ccc.senderTCP(inet); -// ccc.senderUDP(inet); -// peer = new PeerBuilder(new Number160(rnd)).ports(4000+ip).channelClientConfiguration(ccc).bindings(b0).start(); -// System.out.println("started " + peer.peerID()); -// System.err.println("started " + peer.peerID()); -// String command = LocalNATUtils.read(System.in, "command"); -// -// while(command!=null && !command.equals("quit")) { -// if (command.equals("announce")) { -// -// FutureAnnounce res; -// res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); -// res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); -// -// Thread.sleep(3000); -// res = peer.localAnnounce().port(4002).start().awaitUninterruptibly(); -// res = peer.localAnnounce().port(4003).start().awaitUninterruptibly(); -// int size = peer.peerBean().localMap().size(); -// -// -// System.err.println("bootstrap to "+ args[1]); -// PeerAddress relayP = new PeerAddress(relayPeerId, args[1], 5002, 5002); -// peer.bootstrap().peerAddress(relayP).start().awaitUninterruptibly(); -// Thread.sleep(2000); -// -// System.out.println("done " + size); -// -// -// } else if(command.startsWith("ping")) { -// String pingNr = command.split(" ")[1]; -// String pingIp = command.split(" ")[2]; -// Random rnd1 = new Random(Integer.parseInt(pingIp)); -// InetAddress pingInet = InetAddress.getByName("10.0." + pingNr + "." + pingIp); -// Number160 ping160 = new Number160(rnd1); -// PeerAddress pa = new PeerAddress(ping160, pingInet, 4000+Integer.parseInt(pingIp), 4000+Integer.parseInt(pingIp)); -// FuturePing fp = peer.ping().peerAddress(pa).start().awaitUninterruptibly(); -// System.out.println("done "+fp.remotePeer().inetAddress()); -// } -// else { -// System.out.println("empty"); -// } -// command = LocalNATUtils.read(System.in, "command"); -// } -// System.out.println("done"); -// -// } finally { -// System.out.println("finish"); -// if(peer != null) { -// peer.shutdown().awaitUninterruptibly(); -// } -// } -// } + @SuppressWarnings("serial") + @Test + public void testLocalSend() throws Exception { + Peer relayPeer = null; + RemotePeer unr1 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + + + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + System.err.println("test"); + Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); + put("p1", peer1); + put("p2", peer2); + + FutureAnnounce fa1 = peer1.localAnnounce().start().awaitUninterruptibly(); + FutureAnnounce fa2 = peer2.localAnnounce().start().awaitUninterruptibly(); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + FutureDiscover fd2 = peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); + FutureNAT fn1 = pn1.startSetupPortforwarding(fd1).awaitUninterruptibly(); + FutureNAT fn2 = pn2.startSetupPortforwarding(fd2).awaitUninterruptibly(); + if(fn1.isSuccess() && fn2.isSuccess()) { + + // now peer1 and peer2 know each other locally. + PeerAddress punr2 = new PeerAddress(Number160.createHash(1), relayAddress.inetAddress(), + 5001, 5001); + FuturePing fp1 = peer1.ping().peerAddress(punr2).start().awaitUninterruptibly(); + System.err.println(fp1.failedReason() + " /" + fp1.remotePeer()); + } else { + System.err.println("failed: "+ fn1.failedReason() + fn2.failedReason()); + return fn1.failedReason() + fn2.failedReason(); + } + + return "done"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + return LocalNATUtils.shutdown((Peer)get("p1"), (Peer)get("p2")); + } + }); + unr1.waitFor(); + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } @Test public void testLocal() throws Exception { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index 392674ab4..828a8d676 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -6,19 +6,16 @@ import java.net.UnknownHostException; import java.util.Random; -import net.tomp2p.connection.Bindings; import net.tomp2p.futures.FutureDone; import net.tomp2p.holep.NATType; import net.tomp2p.holep.NATTypeDetection; import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; /** @@ -37,13 +34,15 @@ * @author Thomas Bocek * */ -@Ignore +//@Ignore public class TestNATTypeDetection 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 = "wlp3s0"; - static private Peer relayPeer = null; + static private Number160 relayPeerId = new Number160(RND); @Before @@ -58,62 +57,32 @@ public void after() throws IOException, InterruptedException { LocalNATUtils.executeNatSetup("stop", "1"); } - /** - * If you have a terrible lag in InetAddress.getLocalHost(), make sure the - * hostname resolves in the other network domain. - * - * @throws ClassNotFoundException - */ - public static void main(String[] args) throws IOException, - ClassNotFoundException { - LocalNATUtils.handleMain(args); - } - - private static Serializable init(Command command, String ip, int port) - throws UnknownHostException, IOException { - Bindings b = new Bindings(); - Random rnd = new Random(0); - b.addAddress(InetAddress.getByName(ip)); - Peer peer = new PeerBuilder(new Number160(rnd)).ports(port).bindings(b) - .start(); - command.put("peer", peer); - return "initialized " + peer.peerAddress(); - } - private static Serializable discover(final String address, Peer peer) throws UnknownHostException { PeerAddress relayP = new PeerAddress(relayPeerId, address, 5002, 5002); FutureDone type = NATTypeDetection.checkNATType(peer, relayP) .awaitUninterruptibly(); - if (type.isSuccess()) { - return type.object().name(); - } else { - return type.failedReason(); - } - } - - private static Serializable shutdown(Peer peer) { - if (peer != null) { - peer.shutdown().awaitUninterruptibly(); - } - return "shutdown done"; + return type.isSuccess() ? type.object().name() : type.failedReason(); } + @SuppressWarnings("serial") @Test public void testDetection() throws Exception { - relayPeer = null; + Peer relayPeer = null; RemotePeer unr1 = null; RemotePeer unr2 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); final String address = relayAddress.getHostAddress(); - unr1 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "0", + unr1 = LocalNATUtils.executePeer(0, new Command[] { new Command() { // startup @Override public Serializable execute() throws Exception { - return init(this, "10.0.0.2", 5000); + Peer peer = LocalNATUtils.init("10.0.0.2", 5000, 0); + put("peer", peer); + return "initialized " + peer.peerAddress(); } }, new Command() { // detect the NAT type @@ -127,16 +96,18 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { Peer peer = (Peer) get("peer"); - return shutdown(peer); + return LocalNATUtils.shutdown(peer); } } }); - unr2 = LocalNATUtils.executePeer(TestNATTypeDetection.class, "1", + unr2 = LocalNATUtils.executePeer(1, new Command[] { new Command() { // startup @Override public Serializable execute() throws Exception { - return init(this, "10.0.1.2", 5001); + Peer peer = LocalNATUtils.init("10.0.1.2", 5001, 1); + put("peer", peer); + return "initialized " + peer.peerAddress(); } }, new Command() { // detect the NAT type @@ -150,7 +121,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { Peer peer = (Peer) get("peer"); - return shutdown(peer); + return LocalNATUtils.shutdown(peer); } } }); unr1.waitFor(); @@ -162,19 +133,11 @@ public Serializable execute() throws Exception { unr2.getResult(1)); } finally { - System.err.print("shutdown."); - if (relayPeer != null) { - relayPeer.shutdown().awaitUninterruptibly(); - relayPeer = null; - } - System.err.print("."); - if (unr1 != null) { - LocalNATUtils.killPeer(unr1.process()); - } - System.err.println("."); - if (unr2 != null) { - LocalNATUtils.killPeer(unr2.process()); - } + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1, unr2); + System.out.println("."); } } } diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index c9105f50a..f78b33f98 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -45,7 +45,10 @@ # > nat-net.sh stop 0 # # port forwarding, will forward the port in the natX namespace -# > nat-net.sh forward 4000 10.0.0.2 +# > nat-net.sh forward 0 4000 10.0.0.2 +# +# start UPNP deamon in the natX namespace with the external interface NAT_WAN and internal interface NAT_LAN +# > nat-net.sh upnp 0 # # Using the default values, your relay/rendez-vous peer should listen on address 192.168.1.50, # while the unreachable peer should listen on address 10.0.0.2. The unreachable peer needs to @@ -76,6 +79,7 @@ start () { # create 2 namespaces: unreachable and nat ip netns add "unr$1" ip netns add "nat$1" + # setup virtual interfaces ip link add "nat$1_real" type veth peer name "nat$1_wan" ip link set "nat$1_wan" netns "nat$1" @@ -84,21 +88,30 @@ start () { ip link set "unr$1_lan" netns "unr$1" echo "nat$1_real, nat$1_wan created in namespace nat$1." echo "nat$1_lan, unr$1_lan created in namespace unr$1." + # assign IPs ifconfig "nat$1_real" "$NAT_REAL"/24 up ip netns exec "nat$1" ifconfig "nat$1_wan" "$NAT_WAN"/24 up ip netns exec "nat$1" ifconfig "nat$1_lan" "$NAT_LAN"/24 up ip netns exec "unr$1" ifconfig "unr$1_lan" "$UNR_LAN1"/24 up + # adding a virtual interface to simulate two peers behind same NAT - ip netns exec "unr$1" ifconfig "unr$1_lan:0" "$UNR_LAN2"/24 up + # + ip netns exec "unr$1" ifconfig "unr$1_lan:0" "$UNR_LAN2"/24 up + # alternatively, one can use a tun device + #ip netns exec "unr$1" ip tuntap add dev "unr$1_lan2" mode tun + #ip netns exec "unr$1" ifconfig "unr$1_lan2" "$UNR_LAN2"/24 up + # loopback is important or getLocalHost() will hang for a long time! ip netns exec "unr$1" ifconfig "lo" 127.0.0.1 up + # add, modify routing route del -net "$NAT_REAL_NET"/24 dev "nat$1_real" route add -net "$NAT_WAN_NET"/24 dev "nat$1_real" ip netns exec "unr$1" route add default gw "$NAT_LAN" ip netns exec "nat$1" route add default gw "$NAT_WAN" echo "routing set." + # setup NAT ip netns exec "nat$1" echo 1 > /proc/sys/net/ipv4/ip_forward @@ -118,6 +131,7 @@ stop () { ip netns del "unr$1" ip netns del "nat$1" ip link del "nat$1_real" + killall -q miniupnpd } forward () { @@ -127,6 +141,14 @@ forward () { ip netns exec "nat$1" iptables -A FORWARD -d $3 -p udp --dport $2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT } +upnp () { + ip netns exec "nat$1" iptables -t nat -N MINIUPNPD + ip netns exec "nat$1" iptables -t nat -I PREROUTING -j MINIUPNPD + ip netns exec "nat$1" iptables -t filter -N MINIUPNPD + ip netns exec "nat$1" iptables -t filter -I FORWARD -j MINIUPNPD + ip netns exec "nat$1" miniupnpd -i nat$1_wan -a nat$1_lan +} + case "$1" in start) start $2 $3 @@ -145,6 +167,10 @@ case "$1" in forward $2 $3 $4 ;; + upnp) + upnp $2 + ;; + *) echo $"Usage: $0 {start|stop|restart} nr [sym]" exit 1 From 07e5de37ede539e5b763ebdf4e93e2b7b5ff089f Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 28 Jun 2015 18:37:01 +0200 Subject: [PATCH 045/135] Removed local announce, as this was way too fragile. Now the internal IP is stored in the header and peeraddress in case of nat reflection. To not expose fully the IP, the netmask is masked out. That means 192.168.1.77/24 will result in 0.0.0.77. --- .../net/tomp2p/relay/android/UtilsNAT.java | 2 +- .../net/tomp2p/connection/Dispatcher.java | 7 +- .../java/net/tomp2p/connection/PeerBean.java | 11 - .../net/tomp2p/connection/PeerCreator.java | 4 +- .../net/tomp2p/connection/RequestHandler.java | 13 +- .../java/net/tomp2p/connection/Sender.java | 28 +-- .../main/java/net/tomp2p/message/Decoder.java | 39 ++-- .../main/java/net/tomp2p/message/Message.java | 10 + .../tomp2p/message/MessageHeaderCodec.java | 23 ++- .../net/tomp2p/message/TomP2POutbound.java | 7 +- .../java/net/tomp2p/p2p/MaintenanceTask.java | 11 +- core/src/main/java/net/tomp2p/p2p/Peer.java | 19 -- .../main/java/net/tomp2p/p2p/PeerBuilder.java | 12 -- .../tomp2p/p2p/builder/AnnounceBuilder.java | 191 ------------------ .../tomp2p/p2p/builder/DiscoverBuilder.java | 4 +- .../net/tomp2p/p2p/builder/PingBuilder.java | 60 +++++- core/src/main/java/net/tomp2p/peers/IP.java | 170 ++++++++++++++++ .../main/java/net/tomp2p/peers/LocalMap.java | 108 ---------- .../java/net/tomp2p/peers/PeerAddress.java | 164 +++++++++++---- .../java/net/tomp2p/peers/PeerIPFilter.java | 104 +--------- .../main/java/net/tomp2p/rpc/AnnounceRPC.java | 110 ---------- .../java/net/tomp2p/rpc/DispatchHandler.java | 4 +- core/src/main/java/net/tomp2p/rpc/RPC.java | 1 - .../src/main/java/net/tomp2p/utils/Utils.java | 31 +-- core/src/test/java/net/tomp2p/Utils2.java | 2 +- .../java/net/tomp2p/message/TestMessage.java | 33 ++- .../java/net/tomp2p/p2p/TestAnnounce.java | 129 ------------ .../test/java/net/tomp2p/peers/TestIP.java | 54 +++++ .../java/net/tomp2p/peers/TestLocalMap.java | 68 ------- .../net/tomp2p/peers/TestPeerAddress.java | 8 +- .../test/java/net/tomp2p/dht/UtilsDHT2.java | 2 +- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 6 +- .../tomp2p/holep/manual/LocalNATUtils.java | 2 +- .../net/tomp2p/holep/manual/TestNATLocal.java | 75 ++----- .../holep/manual/TestNATTypeDetection.java | 5 +- .../test/java/net/tomp2p/relay/UtilsNAT.java | 2 +- .../src/test/java/net/tomp2p/Utils2.java | 2 +- 37 files changed, 569 insertions(+), 952 deletions(-) delete mode 100644 core/src/main/java/net/tomp2p/p2p/builder/AnnounceBuilder.java create mode 100644 core/src/main/java/net/tomp2p/peers/IP.java delete mode 100644 core/src/main/java/net/tomp2p/peers/LocalMap.java delete mode 100644 core/src/main/java/net/tomp2p/rpc/AnnounceRPC.java delete mode 100644 core/src/test/java/net/tomp2p/p2p/TestAnnounce.java create mode 100644 core/src/test/java/net/tomp2p/peers/TestIP.java delete mode 100644 core/src/test/java/net/tomp2p/peers/TestLocalMap.java diff --git a/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java b/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java index 5af2f4615..0e22f881f 100644 --- a/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java +++ b/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java @@ -218,7 +218,7 @@ public static PeerAddress createAddress(Number160 idSender, String inetSender, i boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false, + PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false,false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; } diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 1cec393a7..9ad7bfec7 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -174,6 +174,11 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa return; } + //NAT reflection, translate back + if(message.sender().isNet4Private()) { + //message.sender(). + } + Responder responder = new DirectResponder(ctx, message); final DispatchHandler myHandler = associatedHandler(message); if (myHandler != null) { @@ -310,7 +315,7 @@ public DispatchHandler associatedHandler(final Message message) { // Search for handler, 0 is ping. If we send with peerid = ZERO, then we // take the first one we found if (recipient.peerId().isZero() && - (message.command() == RPC.Commands.PING.getNr() || message.command() == RPC.Commands.LOCAL_ANNOUNCE.getNr())) { + (message.command() == RPC.Commands.PING.getNr())) { Number160 peerId = peerBeanMaster.serverPeerAddress().peerId(); return searchHandler(peerId, peerId, message.command()); // else we search for the handler that we are responsible for diff --git a/core/src/main/java/net/tomp2p/connection/PeerBean.java b/core/src/main/java/net/tomp2p/connection/PeerBean.java index 99a603c22..8e9daa210 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerBean.java +++ b/core/src/main/java/net/tomp2p/connection/PeerBean.java @@ -21,7 +21,6 @@ import java.util.concurrent.ConcurrentHashMap; import net.tomp2p.p2p.MaintenanceTask; -import net.tomp2p.peers.LocalMap; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; @@ -55,7 +54,6 @@ public class PeerBean { private HolePInitiator holePunchInitiator; private int holePNumberOfHoles; private int holePNumberOfPunches; - private LocalMap localMap; /** * This map is used for all open PeerConnections which are meant to stay @@ -247,15 +245,6 @@ public PeerConnection peerConnection(final Number160 peerId) { return null; } } - - public PeerBean localMap(LocalMap localMap) { - this.localMap = localMap; - return this; - } - - public LocalMap localMap() { - return localMap; - } public PeerBean holePNumberOfHoles(final int holePNumberOfHoles) { this.holePNumberOfHoles = holePNumberOfHoles; diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index 7de3b3205..cc5120c6d 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -223,8 +223,8 @@ private static PeerAddress findPeerAddress(final Number160 peerId, } final PeerSocketAddress peerSocketAddress = new PeerSocketAddress(outsideAddress, channelServerConfiguration. ports().tcpPort(), channelServerConfiguration.ports().udpPort()); - final PeerAddress self = new PeerAddress(peerId, peerSocketAddress, - channelServerConfiguration.isBehindFirewall(), channelServerConfiguration.isBehindFirewall(), false, false, false, + final PeerAddress self = new PeerAddress(peerId, peerSocketAddress, null, + channelServerConfiguration.isBehindFirewall(), channelServerConfiguration.isBehindFirewall(), false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return self; } diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index 47c2bd3af..e09f518e7 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -296,19 +296,18 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo return; } - //NAT reflection, reverse lookup - PeerAddress realAddress = peerBean.localMap().translateReverse(responseMessage.sender()); - if(realAddress != null) { - responseMessage.sender(realAddress); - } + //NAT reflection, change it back, as this will be stored in our peer map that may be queried from other peers + if(message.recipientBeforeTranslation() != null) { + PeerAddress realAddress = responseMessage.sender().changePeerSocketAddress(message.recipientBeforeTranslation()); + responseMessage.sender(realAddress); + } // Stop time measurement of RTT futureResponse.stopRTTMeasurement(); // We got a good answer, let's mark the sender as alive //if its an announce, the peer status will be handled in the RPC - if (responseMessage.command() != RPC.Commands.LOCAL_ANNOUNCE.getNr() - && (responseMessage.isOk() || responseMessage.isNotOk())) { + if (responseMessage.isOk() || responseMessage.isNotOk()) { peerBean.notifyPeerFound(responseMessage.sender(), null, null, futureResponse.getRoundTripTime()); } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 3004c07b5..8583f6fce 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -52,11 +52,9 @@ import net.tomp2p.message.TomP2POutbound; import net.tomp2p.message.TomP2PSinglePacketUDP; import net.tomp2p.p2p.builder.PingBuilder; -import net.tomp2p.peers.LocalMap; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.peers.PeerStatistic; import net.tomp2p.peers.PeerStatusListener; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; @@ -152,14 +150,11 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu } // NAT reflection - rewrite recipient if we found a local address for // the recipient - LocalMap localMap = peerBean.localMap(); - if (localMap != null) { - PeerStatistic peerStatistic = localMap.translate(message.recipient()); - if (peerStatistic != null) { - message.recipient(peerStatistic.peerAddress()); - } - } - + PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); + PeerSocketAddress orig = message.recipient().peerSocketAddress(); + message.saveOriginalRecipientBeforeTranslation(orig); + message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); + removePeerIfFailed(futureResponse, message); // RTT calculation @@ -486,9 +481,7 @@ private ChannelFuture sendTCPCreateChannel(InetSocketAddress recipient, ChannelC handlers.put("heartbeat", new Pair(null, heartBeat)); } - InetSocketAddress reflectedRecipient = Utils.natReflection(recipient, false, dispatcher.peerBean().serverPeerAddress()); - - ChannelFuture channelFuture = channelCreator.createTCP(reflectedRecipient, connectTimeoutMillis, handlers, futureResponse); + ChannelFuture channelFuture = channelCreator.createTCP(recipient, connectTimeoutMillis, handlers, futureResponse); if (peerConnection != null && channelFuture != null) { peerConnection.channelFuture(channelFuture); @@ -576,13 +569,8 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu // NAT reflection - rewrite recipient if we found a local address for // the recipient - LocalMap localMap = peerBean.localMap(); - if (localMap != null) { - PeerStatistic peerStatistic = localMap.translate(message.recipient()); - if (peerStatistic != null) { - message.recipient(peerStatistic.peerAddress()); - } - } + PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); + message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); removePeerIfFailed(futureResponse, message); diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index b7da3f1d2..01db7d3b8 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -54,6 +54,7 @@ public class Decoder { // current state - needs to be deleted if we want to reuse private Message message = null; + private boolean headerDone = false; private Signature signature = null; private int neighborSize = -1; @@ -103,9 +104,9 @@ public boolean decode(ChannelHandlerContext ctx, final ByteBuf buf, InetSocketAd final Attribute attributeInet = ctx.attr(INET_ADDRESS_KEY); attributeInet.set(sender); - if (message == null) { - boolean doneHeader = decodeHeader(buf, recipient, sender); - if (doneHeader) { + if (message == null && !headerDone) { + headerDone = decodeHeader(buf, recipient, sender); + if (headerDone) { // store the sender as an attribute final Attribute attributePeerAddress = ctx.attr(PEER_ADDRESS_KEY); attributePeerAddress.set(message.sender()); @@ -187,22 +188,27 @@ public boolean decodeHeader(final ByteBuf buf, InetSocketAddress recipient, fina return false; } message = MessageHeaderCodec.decodeHeader(buf, recipient, sender); - // we have set the content types already - message.presetContentTypes(true); - + } + + if (message.sender().isNet4Private() && buf.readableBytes() < MessageHeaderCodec.HEADER_PRIVATE_ADDRESS_SIZE) { + return false; + } else if (message.sender().isNet4Private() && buf.readableBytes() >= MessageHeaderCodec.HEADER_PRIVATE_ADDRESS_SIZE){ + PeerSocketAddress internalPeerSocketAddress = PeerSocketAddress.create(buf, true); + message.sender(message.sender().changeInternalPeerSocketAddress(internalPeerSocketAddress)); + } + // we have set the content types already + message.presetContentTypes(true); for (Content content : message.contentTypes()) { - if (content == Content.EMPTY) { - break; - } - if (content == Content.PUBLIC_KEY_SIGNATURE) { - message.setHintSign(); - } - contentTypes.offer(content); + if (content == Content.EMPTY) { + break; } - LOG.debug("Parsed message {}.", message); - return true; + if (content == Content.PUBLIC_KEY_SIGNATURE) { + message.setHintSign(); + } + contentTypes.offer(content); } - return false; + LOG.debug("Parsed message {}.", message); + return true; } public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, InvalidKeySpecException, @@ -606,6 +612,7 @@ public Message prepareFinish() { message.setDone(); contentTypes.clear(); message = null; + headerDone = false; neighborSize = -1; neighborSet = null; keyCollectionSize = -1; diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 6a414e4e0..84b2a2b32 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -203,6 +203,7 @@ public enum Type { private transient boolean content = false; private transient boolean verified = false; private transient boolean sendSelf = false; + private transient PeerSocketAddress recipientBeforeTranslation = null; /** * Creates message with a random ID. @@ -1286,4 +1287,13 @@ public void release() { } } + + public Message saveOriginalRecipientBeforeTranslation(PeerSocketAddress recipientBeforeTranslation) { + this.recipientBeforeTranslation = recipientBeforeTranslation; + return this; + } + + public PeerSocketAddress recipientBeforeTranslation() { + return recipientBeforeTranslation; + } } diff --git a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java index 40e15a6ab..87a49a7bc 100644 --- a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java +++ b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java @@ -44,14 +44,15 @@ public final class MessageHeaderCodec { private MessageHeaderCodec() { } - public static final int HEADER_SIZE = 58; + public static final int HEADER_SIZE = 59; + public static final int HEADER_PRIVATE_ADDRESS_SIZE = 8; /** * Encodes a message object. * * The format looks as follows: 28bit p2p version - 4bit message type - 32bit message id - 8bit message command - 160bit - * sender id - 16bit sender tcp port - 16bit sender udp port - 160bit recipient id - 32bit content types - 8bit options. It total, - * the header is of size 58 bytes. + * sender id - 16bit sender tcp port - 16bit sender udp port - 160bit recipient id - 32bit content types - 8bit sender options - 8bit message options. It total, + * the header is of size 59 bytes. * * @param buffer * The buffer to encode to @@ -70,7 +71,12 @@ public static void encodeHeader(final ByteBuf buffer, final Message message) { buffer.writeBytes(message.recipient().peerId().toByteArray()); // 53 buffer.writeInt(encodeContentTypes(message.contentTypes())); // 57 // three bits for the message options, 5 bits for the sender options - buffer.writeByte((message.sender().options() << 3) | message.options()); // 58 + buffer.writeByte(message.sender().options()); //58 + buffer.writeByte(message.options()); // 59 + if(message.sender().isNet4Private()) { + byte[] ext = message.sender().strip().toByteArray(); + buffer.writeBytes(ext); + } } /** @@ -108,15 +114,16 @@ public static Message decodeHeader(final ByteBuf buffer, final InetSocketAddress message.contentTypes(decodeContentTypes(contentTypes, message)); // set the address as we see it, important for port forwarding // identification - final int options = buffer.readUnsignedByte(); - // three bits for the message options, 5 bits for the sender options - message.options(options & 0x7); - final int senderOptions = options >>> 3; + final int senderOptions = buffer.readUnsignedByte(); final PeerAddress peerAddress = new PeerAddress(senderID, senderSocket.getAddress(), tcpPort, udpPort, senderOptions); + final int messageOptions = buffer.readUnsignedByte(); + message.options(messageOptions); + message.sender(peerAddress); message.senderSocket(senderSocket); message.recipientSocket(recipientSocket); + return message; } diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index 6a9f46000..8156a9873 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -13,7 +13,6 @@ import net.tomp2p.connection.SignatureFactory; import net.tomp2p.storage.AlternativeCompositeByteBuf; -import net.tomp2p.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,18 +49,16 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann // this will release the buffer if (ctx.channel() instanceof DatagramChannel) { - final InetSocketAddress recipientUnreflected; InetSocketAddress recipient; InetSocketAddress sender; if (message.senderSocket() == null) { //in case of a request if(message.recipientRelay()!=null) { //in case of sending to a relay (the relayed flag is already set) - recipientUnreflected = message.recipientRelay().createSocketUDP(); + recipient = message.recipientRelay().createSocketUDP(); } else { - recipientUnreflected = message.recipient().createSocketUDP(); + recipient = message.recipient().createSocketUDP(); } - recipient = Utils.natReflection(recipientUnreflected, true, message.sender()); sender = message.sender().createSocketUDP(0); } else { //in case of a reply diff --git a/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java b/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java index b5a48568f..0430b53d3 100644 --- a/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java +++ b/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java @@ -56,14 +56,9 @@ public void run() { if(peerStatatistic == null) { continue; } - BaseFuture future; - if(peerStatatistic.isLocal()) { - future = peer.localAnnounce().ping().peerAddress(peerStatatistic.peerAddress()).start(); - LOG.debug("Maintenance local ping from {} to {}.", peer.peerAddress(), peerStatatistic.peerAddress()); - } else { - future = peer.ping().peerAddress(peerStatatistic.peerAddress()).start(); - LOG.debug("Maintenance ping from {} to {}.", peer.peerAddress(), peerStatatistic.peerAddress()); - } + BaseFuture future = peer.ping().peerAddress(peerStatatistic.peerAddress()).start(); + LOG.debug("Maintenance ping from {} to {}.", peer.peerAddress(), peerStatatistic.peerAddress()); + peer.notifyAutomaticFutures(future); runningFutures.put(future, peerStatatistic.peerAddress()); COUNTER.incrementAndGet(); diff --git a/core/src/main/java/net/tomp2p/p2p/Peer.java b/core/src/main/java/net/tomp2p/p2p/Peer.java index 91286b0a7..e3b34f927 100644 --- a/core/src/main/java/net/tomp2p/p2p/Peer.java +++ b/core/src/main/java/net/tomp2p/p2p/Peer.java @@ -31,7 +31,6 @@ import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FutureLateJoin; import net.tomp2p.futures.FuturePeerConnection; -import net.tomp2p.p2p.builder.AnnounceBuilder; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.p2p.builder.BroadcastBuilder; import net.tomp2p.p2p.builder.DiscoverBuilder; @@ -40,7 +39,6 @@ import net.tomp2p.p2p.builder.ShutdownBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.rpc.AnnounceRPC; import net.tomp2p.rpc.BroadcastRPC; import net.tomp2p.rpc.DirectDataRPC; import net.tomp2p.rpc.NeighborRPC; @@ -89,7 +87,6 @@ public class Peer { private NeighborRPC neighborRPC; private DirectDataRPC directDataRPC; private BroadcastRPC broadcastRPC; - private AnnounceRPC announceRPC; private volatile boolean shutdown = false; @@ -175,18 +172,6 @@ public Peer broadcastRPC(BroadcastRPC broadcastRPC) { this.broadcastRPC = broadcastRPC; return this; } - - public AnnounceRPC announceRPC() { - if (announceRPC == null) { - throw new RuntimeException("Not enabled, please enable this RPC in PeerMaker"); - } - return announceRPC; - } - - public Peer announceRPC(AnnounceRPC announceRPC) { - this.announceRPC = announceRPC; - return this; - } public DistributedRouting distributedRouting() { if (distributedRouting == null) { @@ -374,8 +359,4 @@ public Peer removeAutomaticFuture(AutomaticFuture automaticFuture) { automaticFutures.remove(automaticFuture); return this; } - - public AnnounceBuilder localAnnounce() { - return new AnnounceBuilder(this); - } } diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index 5e7ec5915..c330ef83d 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -44,11 +44,9 @@ import net.tomp2p.connection.SendBehavior; import net.tomp2p.futures.BaseFuture; import net.tomp2p.p2p.builder.PingBuilder; -import net.tomp2p.peers.LocalMap; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.rpc.AnnounceRPC; import net.tomp2p.rpc.BloomfilterFactory; import net.tomp2p.rpc.BroadcastRPC; import net.tomp2p.rpc.DefaultBloomfilterFactory; @@ -250,10 +248,6 @@ public BaseFuture shutdown() { PeerBean peerBean = peerCreator.peerBean(); - LocalMap localMap = new LocalMap(peerId); - peerBean.localMap(localMap); - peerBean.addPeerStatusListener(localMap); - peerBean.addPeerStatusListener(peerMap); ConnectionBean connectionBean = peerCreator.connectionBean(); @@ -298,11 +292,6 @@ public BaseFuture shutdown() { peer.broadcastRPC(broadcastRPC); } - if (isEnableAnnounceRPC()) { - AnnounceRPC announceRPC = new AnnounceRPC(peerBean, connectionBean); - peer.announceRPC(announceRPC); - } - if (isEnableRouting() && isEnableNeighborRPC()) { DistributedRouting routing = new DistributedRouting(peerBean, peer.neighborRPC()); peer.distributedRouting(routing); @@ -315,7 +304,6 @@ public BaseFuture shutdown() { if (maintenanceTask != null) { maintenanceTask.init(peer, connectionBean.timer()); maintenanceTask.addMaintainable(peerMap); - maintenanceTask.addMaintainable(localMap); } peerBean.maintenanceTask(maintenanceTask); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/AnnounceBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/AnnounceBuilder.java deleted file mode 100644 index 7119618bf..000000000 --- a/core/src/main/java/net/tomp2p/p2p/builder/AnnounceBuilder.java +++ /dev/null @@ -1,191 +0,0 @@ -package net.tomp2p.p2p.builder; - -import java.net.InetAddress; -import java.util.Collection; - -import net.tomp2p.connection.ConnectionConfiguration; -import net.tomp2p.connection.DefaultConnectionConfiguration; -import net.tomp2p.connection.DiscoverResults; -import net.tomp2p.connection.Ports; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureAnnounce; -import net.tomp2p.futures.FutureChannelCreator; -import net.tomp2p.futures.FutureLateJoin; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.p2p.JobScheduler; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.utils.Utils; - -public class AnnounceBuilder implements Builder { - - private final Peer peer; - - private int port = Ports.DEFAULT_PORT; - - private JobScheduler jobScheduler = null; - - private boolean ping = false; - - private PeerAddress peerAddress = null; - - private int intervalMillis = 10000; - - private int repetitions = 5; - - private ConnectionConfiguration connectionConfiguration = null; - - public AnnounceBuilder(Peer peer) { - this.peer = peer; - } - - public int port() { - return port; - } - - public AnnounceBuilder port(int port) { - this.port = port; - return this; - } - - public JobScheduler jobScheduler() { - return jobScheduler; - } - - public AnnounceBuilder jobScheduler(JobScheduler jobScheduler) { - this.jobScheduler = jobScheduler; - return this; - } - - public PeerAddress peerAddress() { - return peerAddress; - } - - public AnnounceBuilder peerAddress(PeerAddress peerAddress) { - this.peerAddress = peerAddress.changePeerId(Number160.ZERO); - return this; - } - - public AnnounceBuilder peerAddressOrig(PeerAddress peerAddress) { - this.peerAddress = peerAddress; - return this; - } - - public AnnounceBuilder intervalMillis(int intervalMillis) { - this.intervalMillis = intervalMillis; - return this; - } - - public int intervalMillis() { - return intervalMillis; - } - - public AnnounceBuilder repetitions(int repetitions) { - this.repetitions = repetitions; - return this; - } - - public int repetitions() { - return repetitions; - } - - public AnnounceBuilder ping() { - this.ping = true; - return this; - } - - public AnnounceBuilder setPing(boolean ping) { - this.ping = ping; - return this; - } - - public boolean isPing() { - return ping; - } - - public FutureAnnounce start() { - - if (connectionConfiguration == null) { - connectionConfiguration = new DefaultConnectionConfiguration(); - } - - FutureAnnounce futureAnnounce = new FutureAnnounce(); - futureAnnounce = ping ? pingAnnounce(futureAnnounce) : announce(futureAnnounce); - if(jobScheduler != null) { - jobScheduler.start(this, intervalMillis, repetitions); - } - return futureAnnounce; - } - - private FutureAnnounce pingAnnounce(final FutureAnnounce futureAnnounce) { - FutureChannelCreator fcc = peer.connectionBean().reservation().create(1, 0); - Utils.addReleaseListener(fcc, futureAnnounce); - fcc.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureChannelCreator future) throws Exception { - if(future.isSuccess()) { - FutureResponse futureResponse = peer.announceRPC().ping(peerAddress, connectionConfiguration, future.channelCreator()); - futureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if(future.isSuccess()) { - futureAnnounce.done(); - } else { - futureAnnounce.failed(future); - } - } - }); - } else { - futureAnnounce.failed(future); - } - } - }); - return futureAnnounce; - } - - private FutureAnnounce announce(final FutureAnnounce futureAnnounce) { - final DiscoverResults discoverResults = peer.connectionBean().channelServer().discoverNetworks().currentDiscoverResults(); - final Collection broadcastAddresses = discoverResults.existingBroadcastAddresses(); - final int size = broadcastAddresses.size(); - final FutureLateJoin futureLateJoin = new FutureLateJoin(size); - if (size > 0) { - FutureChannelCreator fcc = peer.connectionBean().reservation().create(size, 0); - Utils.addReleaseListener(fcc, futureAnnounce); - fcc.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureChannelCreator future) throws Exception { - if (future.isSuccess()) { - addPingListener(futureAnnounce, futureLateJoin); - for (InetAddress broadcastAddress: broadcastAddresses) { - final PeerAddress peerAddress = new PeerAddress(Number160.ZERO, broadcastAddress, - port, port); - FutureResponse validBroadcast = peer.announceRPC().broadcast( - peerAddress, connectionConfiguration, future.channelCreator()); - futureLateJoin.add(validBroadcast); - } - } else { - futureAnnounce.failed(future); - } - } - }); - } else { - futureAnnounce.failed("No broadcast address found. Cannot ping nothing"); - } - return futureAnnounce; - } - - private void addPingListener(final FutureAnnounce futureAnnounce, FutureLateJoin futureLateJoin) { - //we have one successful reply - futureLateJoin.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureLateJoin future) throws Exception { - if(future.futuresDone().size() > 0) { - futureAnnounce.done(); - } else { - futureAnnounce.failed(future); - } - } - }); - } -} diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index d2c10b762..aa2c3c4eb 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -279,14 +279,14 @@ public void operationComplete(FutureResponse future) throws Exception { serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); //manual port forwarding detected, set flag serverAddress = serverAddress.changePortForwarding(true); + serverAddress = serverAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); peer.peerBean().serverPeerAddress(serverAddress); - peer.peerBean().serverPeerAddress().internalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); LOG.info("manual ports, change it to: {}", serverAddress); } else if(expectManualForwarding) { final PeerAddress serverAddressOrig = serverAddress; serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); + serverAddress = serverAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); peer.peerBean().serverPeerAddress(serverAddress); - peer.peerBean().serverPeerAddress().internalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); LOG.info("we were manually forwarding, change it to: {}", serverAddress); } else { diff --git a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java index 7ba503ced..80a4f962e 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java @@ -21,12 +21,14 @@ import net.tomp2p.connection.ConnectionConfiguration; import net.tomp2p.connection.DefaultConnectionConfiguration; +import net.tomp2p.connection.DiscoverResults; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Ports; import net.tomp2p.connection.RequestHandler; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; +import net.tomp2p.futures.FutureLateJoin; import net.tomp2p.futures.FuturePing; import net.tomp2p.futures.FutureResponse; import net.tomp2p.p2p.Peer; @@ -47,6 +49,8 @@ public class PingBuilder { private boolean tcpPing = false; + private boolean broadcast = false; + private PeerConnection peerConnection; private ConnectionConfiguration connectionConfiguration; @@ -92,6 +96,20 @@ public PingBuilder port(int port) { this.port = port; return this; } + + public boolean isBroadcast() { + return broadcast; + } + + public PingBuilder broadcast() { + this.broadcast = true; + return this; + } + + public PingBuilder broadcast(boolean broadcast) { + this.broadcast = broadcast; + return this; + } public boolean isTcpPing() { return tcpPing; @@ -125,6 +143,10 @@ public FuturePing start() { connectionConfiguration = new DefaultConnectionConfiguration(); } + if (broadcast) { + return pingBroadcast(port); + } + if (peerAddress != null) { if (tcpPing) { return ping(peerAddress, false); @@ -205,6 +227,40 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio return futurePing; } + private FuturePing pingBroadcast(final int port) { + final FuturePing futurePing = new FuturePing(); + final DiscoverResults discoverResults = peer.connectionBean().channelServer().discoverNetworks().currentDiscoverResults(); + final int size = discoverResults.existingBroadcastAddresses().size(); + final FutureLateJoin futureLateJoin = new FutureLateJoin(size, 1); + if (size > 0) { + FutureChannelCreator fcc = peer.connectionBean().reservation().create(size, 0); + Utils.addReleaseListener(fcc, futurePing); + fcc.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureChannelCreator future) throws Exception { + if (future.isSuccess()) { + addPingListener(futurePing, futureLateJoin); + for (InetAddress broadcastAddress: discoverResults.existingBroadcastAddresses()) { + final PeerAddress peerAddress = new PeerAddress(Number160.ZERO, broadcastAddress, + port, port); + FutureResponse validBroadcast = peer.pingRPC().pingBroadcastUDP( + peerAddress, future.channelCreator(), connectionConfiguration); + if (!futureLateJoin.add(validBroadcast)) { + // the latejoin future is fininshed if the add returns false + break; + } + } + } else { + futurePing.failed(future); + } + } + }); + } else { + futurePing.failed("No broadcast address found. Cannot ping nothing"); + } + return futurePing; + } + private FuturePing pingPeerConnection(final PeerConnection peerConnection) { final FuturePing futurePing = new FuturePing(); @@ -229,8 +285,8 @@ public void operationComplete(FutureChannelCreator future) throws Exception { - private void addPingListener(final FuturePing futurePing, FutureResponse futureResponse) { - futureResponse.addListener(new BaseFutureAdapter() { + private void addPingListener(final FuturePing futurePing, final BaseFuture baseFuture) { + baseFuture.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureResponse future) throws Exception { if(future.isSuccess()) { diff --git a/core/src/main/java/net/tomp2p/peers/IP.java b/core/src/main/java/net/tomp2p/peers/IP.java new file mode 100644 index 000000000..40a1a3f12 --- /dev/null +++ b/core/src/main/java/net/tomp2p/peers/IP.java @@ -0,0 +1,170 @@ +package net.tomp2p.peers; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class IP { + public static class IPv4 { + private final int bits; + + private IPv4(int bits) { + this.bits = bits; + } + + /** + * 192.168.1.2 with netmask /24 results in 192.168.1.0 + */ + public IPv4 maskWithNetworkMask(final int networkMask) { + if (networkMask == 32) { + return this; + } else { + return new IPv4(bits & (0xFFFFFFFF << (32 - networkMask))); + } + } + + /** + * 192.168.1.2 with netmask /24 results in 0.0.0.2 + */ + public IPv4 maskWithNetworkMaskInv(final int networkMask) { + if (networkMask == 32) { + return this; + } else { + return new IPv4(bits & (0xFFFFFFFF >>> networkMask)); + } + } + + public IPv4 set(IPv4 maskedAddress) { + int newBits = bits | maskedAddress.bits; + return new IPv4(newBits); + } + + public InetAddress toInetAddress() { + byte[] ip = new byte[4]; + ip[0] = (byte) (bits >>> 24); + ip[1] = (byte) (bits >>> 16); + ip[2] = (byte) (bits >>> 8); + ip[3] = (byte) (bits); + try { + return Inet4Address.getByAddress(ip); + } catch (UnknownHostException e) { + //we know the size, so this should not throw an exception + e.printStackTrace(); + return null; + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof IPv4)) { + return false; + } + IPv4 o = (IPv4) obj; + return bits == o.bits; + } + + @Override + public int hashCode() { + return bits; + } + } + + + + public static class IPv6 { + private final long highBits; + private final long lowBits; + + private IPv6(long highBits, long lowBits) { + this.highBits = highBits; + this.lowBits = lowBits; + } + + public IPv6 maskWithNetworkMask(final int networkMask) { + if (networkMask == 128) { + return this; + } else if (networkMask == 64) { + return new IPv6(highBits, 0); + } else if (networkMask > 64) { + final int remainingPrefixLength = networkMask - 64; + return new IPv6(highBits, lowBits & (0xFFFFFFFFFFFFFFFFL << (64 - remainingPrefixLength))); + } else { + return new IPv6(highBits & (0xFFFFFFFFFFFFFFFFL << (64 - networkMask)), 0); + } + } + + public InetAddress toInetAddress() throws UnknownHostException { + byte[] ip = new byte[16]; + ip[0] = (byte) (highBits >>> 56); + ip[1] = (byte) (highBits >>> 48); + ip[2] = (byte) (highBits >>> 40); + ip[3] = (byte) (highBits >>> 32); + ip[4] = (byte) (highBits >>> 24); + ip[5] = (byte) (highBits >>> 16); + ip[6] = (byte) (highBits >>> 8); + ip[7] = (byte) (highBits); + ip[8] = (byte) (lowBits >>> 56); + ip[9] = (byte) (lowBits >>> 48); + ip[10] = (byte) (lowBits >>> 40); + ip[11] = (byte) (lowBits >>> 32); + ip[12] = (byte) (lowBits >>> 24); + ip[13] = (byte) (lowBits >>> 16); + ip[14] = (byte) (lowBits >>> 8); + ip[15] = (byte) (lowBits); + return Inet4Address.getByAddress(ip); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof IPv6)) { + return false; + } + IPv6 o = (IPv6) obj; + return highBits == o.highBits && lowBits == o.lowBits; + } + + @Override + public int hashCode() { + return (int)((highBits^(highBits>>>32)) ^ (lowBits^(lowBits>>>32))); + } + } + + public static IPv4 fromInet4Address(final InetAddress inetAddress) { + if (inetAddress == null) { + throw new IllegalArgumentException("Cannot construct from null."); + } else if (!(inetAddress instanceof Inet4Address)) { + throw new IllegalArgumentException("Must be IPv4."); + } + byte[] buf = ((Inet4Address) inetAddress).getAddress(); + + int ip = ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) + | ((buf[3] & 0xFF) << 0); + return new IPv4(ip); + } + + public static IPv6 fromInet6Address(final InetAddress inetAddress) { + if (inetAddress == null) { + throw new IllegalArgumentException("Cannot construct from null."); + } else if (!(inetAddress instanceof Inet6Address)) { + throw new IllegalArgumentException("Must be IPv6."); + } + byte[] buf = ((Inet6Address) inetAddress).getAddress(); + + long highBits = ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) | ((buf[2] & 0xFFL) << 40) + | ((buf[3] & 0xFFL) << 32) | ((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) + | ((buf[6] & 0xFFL) << 8) | ((buf[7] & 0xFFL) << 0); + + long lowBits = ((buf[8] & 0xFFL) << 56) | ((buf[9] & 0xFFL) << 48) | ((buf[10] & 0xFFL) << 40) + | ((buf[11] & 0xFFL) << 32) | ((buf[12] & 0xFFL) << 24) | ((buf[13] & 0xFFL) << 16) + | ((buf[14] & 0xFFL) << 8) | ((buf[15] & 0xFFL) << 0); + + return new IPv6(highBits, lowBits); + } +} diff --git a/core/src/main/java/net/tomp2p/peers/LocalMap.java b/core/src/main/java/net/tomp2p/peers/LocalMap.java deleted file mode 100644 index 83d27f42f..000000000 --- a/core/src/main/java/net/tomp2p/peers/LocalMap.java +++ /dev/null @@ -1,108 +0,0 @@ -package net.tomp2p.peers; - -import java.util.Collection; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.PeerException; -import net.tomp2p.utils.ConcurrentCacheMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LocalMap implements Maintainable, PeerStatusListener { - - private static final Logger LOG = LoggerFactory.getLogger(LocalMap.class); - final private Number160 self; - - // the storage for the peers that are verified - private final ConcurrentCacheMap localMap; - private final ConcurrentCacheMap localMapRev; - private final ConcurrentCacheMap offlineMap; - private final int[] intervalSeconds; - - public LocalMap(Number160 self) { - this(self, new LocalMapConf()); - } - - public LocalMap(Number160 self, LocalMapConf localMapConf) { - localMap = new ConcurrentCacheMap(localMapConf.localMapTimout(), localMapConf.localMapSize()); - localMapRev = new ConcurrentCacheMap(localMapConf.localMapRevTimeout(), localMapConf.localMapRevSize()); - offlineMap = new ConcurrentCacheMap(localMapConf.offlineMapTimout(), localMapConf.offlineMapSize()); - intervalSeconds = localMapConf.intervalSeconds(); - this.self = self; - } - - @Override - public PeerStatistic nextForMaintenance(Collection notInterestedAddresses) { - for(PeerStatistic peerStatistic:localMap.values()) { - if(DefaultMaintenance.needMaintenance(peerStatistic, intervalSeconds)) { - return peerStatistic; - } - } - return null; - } - - @Override - public boolean peerFailed(PeerAddress remotePeer, PeerException exception) { - PeerStatistic ps = localMap.remove(remotePeer.peerId()); - localMapRev.remove(remotePeer.peerId()); - offlineMap.put(remotePeer.peerId(), Boolean.TRUE); - return ps != null; - } - - @Override - public boolean peerFound(PeerAddress remotePeer, PeerAddress referrer, PeerConnection peerConnection, RTT roundTripTime) { - //do nothing, here we get to know all the peers, we are interested only in those we have stored - return false; - } - - public boolean peerFound(PeerAddress remotePeer, PeerAddress referrer) { - //this is called from the RPC method, here we only get the local peers - LOG.debug("local peer {} is online reporter was {}", remotePeer, referrer); - //we don't need to store our peerId - if(remotePeer.peerId().equals(self)) { - return false; - } - if(remotePeer.peerId().equals(Number160.ZERO)) { - return false; - } - - boolean firstHand = referrer == null; - //if we got contacted by this peer, but we did not initiate the connection - boolean secondHand = remotePeer.equals(referrer); - - if (firstHand || secondHand) { - offlineMap.remove(remotePeer.peerId()); - PeerStatistic peerStatatistic = PeerMap.updateExistingVerifiedPeerAddress(localMap, remotePeer, firstHand, null); - if(peerStatatistic == null) { - peerStatatistic = new PeerStatistic(remotePeer); - localMap.put(remotePeer.peerId(), peerStatatistic); - } - peerStatatistic.successfullyChecked(); - peerStatatistic.local(); - return true; - } - return false; - } - - public PeerStatistic translate(PeerAddress remotePeer) { - PeerStatistic peerStatistic = localMap.get(remotePeer.peerId()); - if(peerStatistic != null) { - localMapRev.put(remotePeer.peerId(), remotePeer); - } - return peerStatistic; - } - - public PeerAddress translateReverse(PeerAddress remotePeer) { - PeerAddress peerAddress = localMapRev.get(remotePeer.peerId()); - return peerAddress; - } - - public int size() { - return localMap.size(); - } - - public Collection peers() { - return localMap.values(); - } -} diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 53fad6616..d4b9e468c 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -21,6 +21,9 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; @@ -58,19 +61,23 @@ public final class PeerAddress implements Comparable, Serializable public static final int MIN_SIZE = 30; private static final long serialVersionUID = -1316622724169272306L; - private static final int NET6 = 1; // 0001 - private static final int FIREWALL_UDP = 2; // 0010 - private static final int FIREWALL_TCP = 4; // 0100 - // indicates that a relay is used. // 1000 - private static final int RELAYED = 8; + private static final int NET6 = 1; // 0000001 + private static final int FIREWALL_UDP = 2; // 0000010 + private static final int FIREWALL_TCP = 4; // 0000100 + // indicates that a relay is used. + private static final int RELAYED = 8; // 0001000 // indicates that the peer is slow (because relayed) - private static final int SLOW = 16; + private static final int SLOW = 16; // 0010000 // indicates the peer forwarded the ports either manually or with UPNP - private static final int PORT_FORWARDING = 32; - + private static final int PORT_FORWARDING = 32; // 0100000 + // indicate IPv4 with the internal IP + private static final int NET4_PRIVATE = 64; // 1000000 + // network information private final Number160 peerId; private final PeerSocketAddress peerSocketAddress; + private final PeerSocketAddress internalPeerSocketAddress; + private final int internalNetworkPrefix; // connection information private final boolean net6; @@ -79,6 +86,7 @@ public final class PeerAddress implements Comparable, Serializable private final boolean relayed; private final boolean slow; private final boolean portForwarding; + private final boolean net4Private; // we can make the hash final as it never changes, and this class is used // multiple times in maps. A new peer is always added to the peermap, so @@ -104,9 +112,7 @@ public final class PeerAddress implements Comparable, Serializable private static final int HEADER_SIZE = 2; // count both ports, UDP and TCP private static final int PORTS_SIZE = 4; - - //TODO: make integrate this - private PeerSocketAddress internalPeerSocketAddress; + // used for the relay bit shifting private static final int MASK_1F = 0x1f; // 0001 1111 private static final int MASK_07 = 0x7; // 0000 0111 @@ -144,6 +150,7 @@ public PeerAddress(final byte[] me, final int initialOffset) { this.relayed = (options & RELAYED) > 0; this.slow = (options & SLOW) > 0; this.portForwarding = (options & PORT_FORWARDING) > 0; + this.net4Private = (options & NET4_PRIVATE) > 0; final int relays = me[offset++] & Utils.MASK_FF; // first: three bits are the size 1,2,4 // 000 means no relays @@ -166,6 +173,14 @@ public PeerAddress(final byte[] me, final int initialOffset) { this.peerSocketAddress = PeerSocketAddress.create(me, isIPv4(), offset); offset = this.peerSocketAddress.offset(); + if(isNet4Private()) { + this.internalPeerSocketAddress = PeerSocketAddress.create(me, true, offset); + offset = this.internalPeerSocketAddress.offset(); + } else { + this.internalPeerSocketAddress = null; + } + this.internalNetworkPrefix = -1; + if (relaySize > 0) { this.peerSocketAddresses = new ArrayList(relaySize); for (int i = 0; i < relaySize; i++) { @@ -199,6 +214,7 @@ public PeerAddress(final ByteBuf channelBuffer) { this.relayed = (options & RELAYED) > 0; this.slow = (options & SLOW) > 0; this.portForwarding = (options & PORT_FORWARDING) > 0; + this.net4Private = (options & NET4_PRIVATE) > 0; final int relays = channelBuffer.readUnsignedByte(); // first: three bits are the size 1,2,4 // 000 means no relays @@ -219,6 +235,8 @@ public PeerAddress(final ByteBuf channelBuffer) { this.peerId = new Number160(me); this.peerSocketAddress = PeerSocketAddress.create(channelBuffer, isIPv4()); + this.internalPeerSocketAddress = isNet4Private() ? PeerSocketAddress.create(channelBuffer, true) : null; + this.internalNetworkPrefix = -1; if (relaySize > 0) { this.peerSocketAddresses = new ArrayList(relaySize); @@ -275,12 +293,14 @@ public PeerAddress(final Number160 id, final InetAddress address) { * @param peerSocketAddresses * the relay peers */ - public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress, + public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress, final PeerSocketAddress internalPeerSocketAddress, final boolean firewalledTCP, final boolean firewalledUDP, final boolean isRelayed, - boolean isSlow, boolean portForwarding, final Collection peerSocketAddresses) { + boolean isSlow, boolean portForwarding, boolean net4Private, final Collection peerSocketAddresses) { this.peerId = id; int size = Number160.BYTE_ARRAY_SIZE; this.peerSocketAddress = peerSocketAddress; + this.internalPeerSocketAddress = internalPeerSocketAddress; + this.internalNetworkPrefix = internalPeerSocketAddress == null ? -1: prefix(internalPeerSocketAddress.inetAddress()); this.hashCode = id.hashCode(); this.net6 = peerSocketAddress.inetAddress() instanceof Inet6Address; this.firewalledUDP = firewalledUDP; @@ -288,8 +308,10 @@ public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress this.relayed = isRelayed; this.slow = isSlow; this.portForwarding = portForwarding; + this.net4Private = net4Private; // header + TCP port + UDP port size += HEADER_SIZE + PORTS_SIZE + (net6 ? Utils.IPV6_BYTES : Utils.IPV4_BYTES); + size += net4Private? Utils.IPV4_BYTES + PORTS_SIZE : 0; if (peerSocketAddresses == null) { this.peerSocketAddresses = EMPTY_PEER_SOCKET_ADDRESSES; this.relayType = EMPTY_RELAY_TYPE; @@ -328,7 +350,7 @@ public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress */ public PeerAddress(final Number160 peerId, final InetAddress inetAddress, final int tcpPort, final int udpPort) { - this(peerId, new PeerSocketAddress(inetAddress, tcpPort, udpPort), false, false, false, false, false, EMPTY_PEER_SOCKET_ADDRESSES); + this(peerId, new PeerSocketAddress(inetAddress, tcpPort, udpPort), null, false, false, false, false, false, false, EMPTY_PEER_SOCKET_ADDRESSES); } /** @@ -347,8 +369,9 @@ public PeerAddress(final Number160 peerId, final InetAddress inetAddress, final */ public PeerAddress(final Number160 id, final InetAddress inetAddress, final int tcpPort, final int udpPort, final int options) { - this(id, new PeerSocketAddress(inetAddress, tcpPort, udpPort), isFirewalledTCP(options), - isFirewalledUDP(options), isRelay(options), isSlow(options), isPortForwarding(options), EMPTY_PEER_SOCKET_ADDRESSES); + this(id, new PeerSocketAddress(inetAddress, tcpPort, udpPort), null, isFirewalledTCP(options), + isFirewalledUDP(options), isRelay(options), isSlow(options), isPortForwarding(options), + isNet4Private(options), EMPTY_PEER_SOCKET_ADDRESSES); } /** @@ -429,6 +452,9 @@ public int toByteArray(final byte[] me, final int offset) { // we store both the addresses of the peer and the relays. Currently this is not needed, as we don't consider // asymmetric relays. But in future we may. newOffset = peerSocketAddress.toByteArray(me, newOffset); + if(isNet4Private()) { + newOffset = strip().toByteArray(me, newOffset); + } for (PeerSocketAddress psa : peerSocketAddresses) { newOffset = psa.toByteArray(me, newOffset); @@ -504,6 +530,9 @@ public byte options() { if(portForwarding) { result |= PORT_FORWARDING; } + if(net4Private) { + result |= NET4_PRIVATE; + } return result; } @@ -621,6 +650,10 @@ public boolean isPortForwarding() { return portForwarding; } + public boolean isNet4Private() { + return net4Private; + } + /** * Create a new PeerAddress and change the relayed status. @@ -629,8 +662,8 @@ public boolean isPortForwarding() { * @return The newly created peer address */ public PeerAddress changeRelayed(final boolean isRelayed) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, isRelayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, isRelayed, slow, portForwarding, net4Private, + peerSocketAddresses); } /** @@ -641,13 +674,13 @@ public PeerAddress changeRelayed(final boolean isRelayed) { * @return The newly created peer address */ public PeerAddress changeSlow(final boolean isSlow) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, isSlow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, isSlow, portForwarding, net4Private, + peerSocketAddresses); } public PeerAddress changePortForwarding(final boolean portForwarding) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); } /** @@ -658,8 +691,8 @@ public PeerAddress changePortForwarding(final boolean portForwarding) { * @return The newly created peer address */ public PeerAddress changeFirewalledUDP(final boolean firewalledUDP) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); } /** @@ -670,8 +703,8 @@ public PeerAddress changeFirewalledUDP(final boolean firewalledUDP) { * @return The newly created peer address */ public PeerAddress changeFirewalledTCP(final boolean firewalledTCP) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); } /** @@ -685,7 +718,7 @@ public PeerAddress changeFirewalledTCP(final boolean firewalledTCP) { */ public PeerAddress changePorts(final int tcpPort, final int udpPort) { return new PeerAddress(peerId, new PeerSocketAddress(peerSocketAddress.inetAddress(), tcpPort, - udpPort), firewalledTCP, firewalledUDP, relayed, slow, portForwarding, peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + udpPort), internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, peerSocketAddresses); } /** @@ -697,7 +730,7 @@ public PeerAddress changePorts(final int tcpPort, final int udpPort) { */ public PeerAddress changeAddress(final InetAddress inetAddress) { return new PeerAddress(peerId, new PeerSocketAddress(inetAddress, peerSocketAddress.tcpPort(), - peerSocketAddress.udpPort()), firewalledTCP, firewalledUDP, relayed, slow, portForwarding, peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + peerSocketAddress.udpPort()), internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, peerSocketAddresses); } /** @@ -708,18 +741,23 @@ public PeerAddress changeAddress(final InetAddress inetAddress) { * @return The newly created peer address */ public PeerAddress changePeerId(final Number160 peerId) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); } public PeerAddress changePeerSocketAddresses(Collection peerSocketAddresses) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); } public PeerAddress changePeerSocketAddress(PeerSocketAddress peerSocketAddress) { - return new PeerAddress(peerId, peerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, - peerSocketAddresses).internalPeerSocketAddress(internalPeerSocketAddress); + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, + peerSocketAddresses); + } + + public PeerAddress changeInternalPeerSocketAddress(PeerSocketAddress internalPeerSocketAddress) { + return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, internalPeerSocketAddress!=null, + peerSocketAddresses); } /** @@ -787,6 +825,10 @@ private static boolean isSlow(final int options) { private static boolean isPortForwarding(final int options) { return ((options & Utils.MASK_FF) & PORT_FORWARDING) > 0; } + + private static boolean isNet4Private(final int options) { + return ((options & Utils.MASK_FF) & NET4_PRIVATE) > 0; + } /** * Calculates the size based on the two header bytes. @@ -815,7 +857,10 @@ public static int size(final int options, final int relays) { int size = HEADER_SIZE + PORTS_SIZE + Number160.BYTE_ARRAY_SIZE; if (isNet6(options)) { size += Utils.IPV6_BYTES; - } else { + } else if(isNet4Private(options)) { + size += Utils.IPV4_BYTES + Utils.IPV4_BYTES + PORTS_SIZE; + } + else { size += Utils.IPV4_BYTES; } // count the relays @@ -841,8 +886,51 @@ public PeerSocketAddress internalPeerSocketAddress() { return internalPeerSocketAddress; } - public PeerAddress internalPeerSocketAddress(PeerSocketAddress internalPeerSocketAddress) { - this.internalPeerSocketAddress = internalPeerSocketAddress; - return this; + public PeerSocketAddress strip() { + if(internalPeerSocketAddress == null) { + throw new IllegalArgumentException("internal peer socket must be set"); + } + if(internalNetworkPrefix == -1) { + return internalPeerSocketAddress; + } + IP.IPv4 masked = IP.fromInet4Address(internalPeerSocketAddress.inetAddress()); + masked = masked.maskWithNetworkMaskInv(internalNetworkPrefix); + final InetAddress inet = masked.toInetAddress(); + return new PeerSocketAddress(inet, internalPeerSocketAddress.tcpPort(), internalPeerSocketAddress.udpPort()); + } + + public InetAddress calcInternalInetAddress(InetAddress remote) { + if(internalNetworkPrefix == -1) { + throw new IllegalArgumentException("network prefix must be set"); + } + if(internalPeerSocketAddress == null) { + throw new IllegalArgumentException("internal peer socket must be set"); + } + IP.IPv4 mask = IP.fromInet4Address(internalPeerSocketAddress.inetAddress()); + mask = mask.maskWithNetworkMask(internalNetworkPrefix); + IP.IPv4 masked = IP.fromInet4Address(remote); + masked = masked.maskWithNetworkMaskInv(internalNetworkPrefix); + return mask.set(masked).toInetAddress(); + } + + private int prefix(InetAddress inetAddress) { + NetworkInterface networkInterface; + try { + networkInterface = NetworkInterface.getByInetAddress(internalPeerSocketAddress.inetAddress()); + if(networkInterface == null) { + return -1; + } + if(networkInterface.getInterfaceAddresses().size() <= 0) { + return -1; + } + InterfaceAddress iface = networkInterface.getInterfaceAddresses().get(0); + if(iface == null) { + return -1; + } + return iface.getNetworkPrefixLength(); + } catch (SocketException e) { + e.printStackTrace(); + return -1; + } } } diff --git a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java index a6a0c70fa..4629f1767 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java +++ b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java @@ -18,7 +18,6 @@ import java.net.Inet4Address; import java.net.Inet6Address; -import java.net.InetAddress; import java.util.Collection; /** @@ -47,20 +46,20 @@ public boolean rejectPeerMap(final PeerAddress peerAddress, final PeerMap peerMa @Override public boolean rejectPreRouting(PeerAddress peerAddress, Collection all) { if (peerAddress.inetAddress() instanceof Inet4Address) { - IPv4 ipv4 = IPv4.fromInetAddress(peerAddress.inetAddress()); + IP.IPv4 ipv4 = IP.fromInet4Address(peerAddress.inetAddress()); for (PeerAddress inMap : all) { if (inMap.inetAddress() instanceof Inet4Address) { - IPv4 ipv4Test = IPv4.fromInetAddress(inMap.inetAddress()); + IP.IPv4 ipv4Test = IP.fromInet4Address(inMap.inetAddress()); if (ipv4.maskWithNetworkMask(mask4).equals(ipv4Test.maskWithNetworkMask(mask4))) { return true; } } } } else { - IPv6 ipv6 = IPv6.fromInetAddress(peerAddress.inetAddress()); + IP.IPv6 ipv6 = IP.fromInet6Address( peerAddress.inetAddress()); for (PeerAddress inMap : all) { if (inMap.inetAddress() instanceof Inet6Address) { - IPv6 ipv6Test = IPv6.fromInetAddress(inMap.inetAddress()); + IP.IPv6 ipv6Test = IP.fromInet6Address(inMap.inetAddress()); if (ipv6.maskWithNetworkMask(mask6).equals(ipv6Test.maskWithNetworkMask(mask6))) { return true; } @@ -70,98 +69,5 @@ public boolean rejectPreRouting(PeerAddress peerAddress, Collection return false; } - private static class IPv4 { - private final int bits; - - private IPv4(int bits) { - this.bits = bits; - } - - public IPv4 maskWithNetworkMask(final int networkMask) { - if (networkMask == 32) { - return this; - } else { - return new IPv4(bits & (0xFFFFFFFF << (32 - networkMask))); - } - } - - public static IPv4 fromInetAddress(final InetAddress inetAddress) { - if (inetAddress == null) { - throw new IllegalArgumentException("Cannot construct from null."); - } else if (!(inetAddress instanceof Inet4Address)) { - throw new IllegalArgumentException("Must be IPv4."); - } - byte[] buf = ((Inet4Address) inetAddress).getAddress(); - - int ip = ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) - | ((buf[3] & 0xFF) << 0); - return new IPv4(ip); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof IPv4)) { - return false; - } - IPv4 o = (IPv4) obj; - return bits == o.bits; - } - } - - private static class IPv6 { - private final long highBits; - private final long lowBits; - - private IPv6(long highBits, long lowBits) { - this.highBits = highBits; - this.lowBits = lowBits; - } - - public IPv6 maskWithNetworkMask(final int networkMask) { - if (networkMask == 128) { - return this; - } else if (networkMask == 64) { - return new IPv6(highBits, 0); - } else if (networkMask > 64) { - final int remainingPrefixLength = networkMask - 64; - return new IPv6(highBits, lowBits & (0xFFFFFFFFFFFFFFFFL << (64 - remainingPrefixLength))); - } else { - return new IPv6(highBits & (0xFFFFFFFFFFFFFFFFL << (64 - networkMask)), 0); - } - } - - public static IPv6 fromInetAddress(final InetAddress inetAddress) { - if (inetAddress == null) { - throw new IllegalArgumentException("Cannot construct from null."); - } else if (!(inetAddress instanceof Inet6Address)) { - throw new IllegalArgumentException("Must be IPv6."); - } - byte[] buf = ((Inet6Address) inetAddress).getAddress(); - - long highBits = ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) | ((buf[2] & 0xFFL) << 40) - | ((buf[3] & 0xFFL) << 32) | ((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) - | ((buf[6] & 0xFFL) << 8) | ((buf[7] & 0xFFL) << 0); - - long lowBits = ((buf[8] & 0xFFL) << 56) | ((buf[9] & 0xFFL) << 48) | ((buf[10] & 0xFFL) << 40) - | ((buf[11] & 0xFFL) << 32) | ((buf[12] & 0xFFL) << 24) | ((buf[13] & 0xFFL) << 16) - | ((buf[14] & 0xFFL) << 8) | ((buf[15] & 0xFFL) << 0); - - return new IPv6(highBits, lowBits); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof IPv6)) { - return false; - } - IPv6 o = (IPv6) obj; - return highBits == o.highBits && lowBits == o.lowBits; - } - } + } diff --git a/core/src/main/java/net/tomp2p/rpc/AnnounceRPC.java b/core/src/main/java/net/tomp2p/rpc/AnnounceRPC.java deleted file mode 100644 index 603ed2c47..000000000 --- a/core/src/main/java/net/tomp2p/rpc/AnnounceRPC.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2009 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.rpc; - -import net.tomp2p.connection.ChannelCreator; -import net.tomp2p.connection.ConnectionBean; -import net.tomp2p.connection.ConnectionConfiguration; -import net.tomp2p.connection.PeerBean; -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.RequestHandler; -import net.tomp2p.connection.Responder; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.peers.PeerAddress; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This Quit RPC is used to send friendly shutdown messages by peers that are - * shutdown regularly. - * - * @author Thomas Bocek - * - */ -public class AnnounceRPC extends DispatchHandler { - - private static final Logger LOG = LoggerFactory.getLogger(AnnounceRPC.class); - - /** - * Constructor that registers this RPC with the message handler. - * - * @param peerBean - * The peer bean that contains data that is unique for each peer - * @param connectionBean - * The connection bean that is unique per connection (multiple - * peers can share a single connection) - */ - public AnnounceRPC(final PeerBean peerBean, final ConnectionBean connectionBean) { - super(peerBean, connectionBean); - register(RPC.Commands.LOCAL_ANNOUNCE.getNr()); - } - - public FutureResponse broadcast(final PeerAddress remotePeer, final ConnectionConfiguration configuration, - final ChannelCreator channelCreator) { - final Message message = createMessage(remotePeer, RPC.Commands.LOCAL_ANNOUNCE.getNr(), Type.REQUEST_FF_1); - - FutureResponse futureResponse = new FutureResponse(message); - final RequestHandler requestHandler = new RequestHandler(futureResponse, - peerBean(), connectionBean(), configuration); - LOG.debug("send ANNOUNCE BROADCAST message {}", message); - return requestHandler.fireAndForgetBroadcastUDP(channelCreator); - } - - public FutureResponse ping(final PeerAddress remotePeer, final ConnectionConfiguration configuration, - final ChannelCreator channelCreator) { - final Message message = createMessage(remotePeer, RPC.Commands.LOCAL_ANNOUNCE.getNr(), Type.REQUEST_1); - - FutureResponse futureResponse = new FutureResponse(message); - final RequestHandler requestHandler = new RequestHandler(futureResponse, - peerBean(), connectionBean(), configuration); - LOG.debug("send ANNOUNCE PING message {}", message); - futureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if(future.isSuccess()) { - peerBean().localMap().peerFound(message.recipient(), null); - } - } - }); - return requestHandler.sendBroadcastUDP(channelCreator); - } - - @Override - public void handleResponse(final Message message, PeerConnection peerConnection, final boolean sign, - Responder responder) throws Exception { - if (!(message.command() == RPC.Commands.LOCAL_ANNOUNCE.getNr())) { - throw new IllegalArgumentException("Message content is wrong"); - } - LOG.debug("received ANNOUNCE message {}", message); - if(message.type() == Type.REQUEST_FF_1) { - responder.responseFireAndForget(); - //add to local map - peerBean().localMap().peerFound(message.sender(), message.sender()); - //this will eventually trigger maintenance - } else if(message.type() == Type.REQUEST_1) { - //only reply if we are the intended recipient for this broadcast message - if(message.recipient().peerId().equals(peerBean().serverPeerAddress().peerId())) { - responder.response(createResponseMessage(message, Type.OK)); - } - //add to local map - peerBean().localMap().peerFound(message.sender(), message.sender()); - } - } -} diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index 95333652a..8497d7fa6 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -153,7 +153,9 @@ public static Message createResponseMessage(final Message requestMessage, final public void forwardMessage(final Message requestMessage, PeerConnection peerConnection, Responder responder) { // Here, we need a referral since we got contacted and we don't know if // we can contact the peer with its address. The peer may be behind a NAT. - if(requestMessage.command() != RPC.Commands.LOCAL_ANNOUNCE.getNr()) { + + //TODO: figure out how to include this. The only thing we currently missing are the ports + if(!requestMessage.sender().isNet4Private()) { peerBean.notifyPeerFound(requestMessage.sender(), requestMessage.sender(), peerConnection, null); } diff --git a/core/src/main/java/net/tomp2p/rpc/RPC.java b/core/src/main/java/net/tomp2p/rpc/RPC.java index 7e0c3a2cb..3fb743a1c 100644 --- a/core/src/main/java/net/tomp2p/rpc/RPC.java +++ b/core/src/main/java/net/tomp2p/rpc/RPC.java @@ -28,7 +28,6 @@ public enum Commands{ HOLEP(), GET_LATEST_WITH_DIGEST(), GCM(), - LOCAL_ANNOUNCE(), REPLICA_PUT(), DIGEST_ALL_BLOOMFILTER(); public byte getNr() { diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index 955e11c9f..11771f22c 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -32,7 +32,6 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; @@ -926,36 +925,28 @@ public static int randomPositiveInt(int upperBound) { return randomInt; } - public static InetSocketAddress natReflection(InetSocketAddress recipient, boolean udp, PeerAddress self) { - if(self.isPortForwarding()) { + public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress self) { + if(self.isPortForwarding() && recipient.isPortForwarding()) { //check for NAT reflection - if(recipient.getAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null) { + if(recipient.inetAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null && recipient.internalPeerSocketAddress()!=null) { //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. - if(udp && recipient.getPort() == self.udpPort() ) { + if(recipient.udpPort() == self.udpPort() ) { //we send it to ourself, change it to something local try { - //TODO: pick one of the discovered interfaces the server is listening to and prefer localhost if available - return new InetSocketAddress(InetAddress.getLocalHost(), self.internalPeerSocketAddress().udpPort()); + + return new PeerSocketAddress(InetAddress.getLocalHost(), self.internalPeerSocketAddress().tcpPort(), + self.internalPeerSocketAddress().udpPort()); } catch (UnknownHostException e) { e.printStackTrace(); - return recipient; - } - } else if(!udp && recipient.getPort() == self.tcpPort()) { - //we send it to ourself, change it to something local - try { - //TODO: pick one of the discovered interfaces the server is listening to and prefer localhost if available - return new InetSocketAddress(InetAddress.getLocalHost(), self.internalPeerSocketAddress().tcpPort()); - } catch (UnknownHostException e) { - e.printStackTrace(); - return recipient; + return null; } } else { - //the recipient is in our network, but its not ourself - //TODO: the peer must send its internal IP, in order to be reachable + InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); + return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); } } } - return recipient; + return recipient.peerSocketAddress(); } /** diff --git a/core/src/test/java/net/tomp2p/Utils2.java b/core/src/test/java/net/tomp2p/Utils2.java index 097e1718e..c2aad8202 100644 --- a/core/src/test/java/net/tomp2p/Utils2.java +++ b/core/src/test/java/net/tomp2p/Utils2.java @@ -101,7 +101,7 @@ public static PeerAddress createAddress(Number160 idSender, String inetSender, i int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false, + PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; } diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index 9811cada3..c5bd7b99e 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -508,7 +508,7 @@ public void testRelay() throws Exception { psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), true, true, true, true, false, + InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, false, false, psa); Message m1 = Utils2.createDummyMessage(); @@ -536,7 +536,36 @@ public void testRelay2() throws Exception { psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), true, true, true, true, true, + InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, true, false, + psa); + + Message m1 = Utils2.createDummyMessage(); + Collection tmp = new ArrayList(); + tmp.add(pa3); + m1.neighborsSet(new NeighborSet(100, tmp)); + + Message m2 = encodeDecode(m1); + Assert.assertEquals(tmp, m2.neighborsSetList().get(0).neighbors()); + compareMessage(m1, m2); + + } + + @Test + public void testInternalPeerSocket() throws Exception { + Collection psa = new ArrayList(); + psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); + psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); + psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); + PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( + InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), new PeerSocketAddress( + InetAddress.getByName("0.0.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), true, true, true, true, true, true, psa); Message m1 = Utils2.createDummyMessage(); diff --git a/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java b/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java deleted file mode 100644 index 29eca26df..000000000 --- a/core/src/test/java/net/tomp2p/p2p/TestAnnounce.java +++ /dev/null @@ -1,129 +0,0 @@ -package net.tomp2p.p2p; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Random; - -import net.tomp2p.Utils2; -import net.tomp2p.connection.DiscoverResults; -import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.FutureAnnounce; -import net.tomp2p.futures.FuturePing; -import net.tomp2p.peers.Number160; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -public class TestAnnounce { - - @Rule - public TestRule watcher = new TestWatcher() { - protected void starting(Description description) { - System.out.println("Starting test: " + description.getMethodName()); - } - }; - - /** - * Start with -Djava.net.preferIPv4Stack=true - * @throws Exception - */ - @Test - public void testLocalAnnounce() throws Exception { - final Random rnd = new Random(42); - Peer master = null; - try { - // setup - Peer[] peers = Utils2.createNonMaintenanceNodes(100, rnd, 4001); - master = peers[0]; - if(!hasBroadcastAddress(master)) { - return; - } - // do testing - List tmp = new ArrayList(); - // we start from 1, because a broadcast to ourself will not get - // replied. - for (int i = 1; i < peers.length; i++) { - FutureAnnounce res = peers[i].localAnnounce().port(4001).start(); - tmp.add(res); - } - for(FutureAnnounce f:tmp) { - f.awaitUninterruptibly(); - } - //check the local map - for(int i=0;i broadcastAddresses = discoverResults.existingBroadcastAddresses(); - return broadcastAddresses.size() > 0; - } -} diff --git a/core/src/test/java/net/tomp2p/peers/TestIP.java b/core/src/test/java/net/tomp2p/peers/TestIP.java new file mode 100644 index 000000000..fdd5f029e --- /dev/null +++ b/core/src/test/java/net/tomp2p/peers/TestIP.java @@ -0,0 +1,54 @@ +package net.tomp2p.peers; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.junit.Assert; +import org.junit.Test; + +public class TestIP { + @Test + public void testMask4() throws UnknownHostException { + InetAddress inet = Inet4Address.getByName("192.168.1.44"); + IP.IPv4 v4 = IP.fromInet4Address(inet); + InetAddress inet2 = v4.toInetAddress(); + Assert.assertEquals(inet, inet2); + } + + @Test + public void testMask6() throws UnknownHostException { + InetAddress inet = Inet6Address.getByName("2607:f0d0:1002:0051:0000:0000:0000:0004"); + IP.IPv6 v6 = IP.fromInet6Address(inet); + InetAddress inet2 = v6.toInetAddress(); + Assert.assertEquals(inet, inet2); + } + + @Test + public void testMask4with24() throws UnknownHostException { + InetAddress inet = Inet4Address.getByName("192.168.1.44"); + IP.IPv4 v4 = IP.fromInet4Address(inet); + v4 = v4.maskWithNetworkMaskInv(24); + InetAddress inet2 = Inet4Address.getByName("0.0.0.44"); + InetAddress inet3 = v4.toInetAddress(); + Assert.assertEquals(inet2, inet3); + } + + @Test + public void testMask4Set() throws UnknownHostException { + InetAddress inet = Inet4Address.getByName("10.10.10.44"); + IP.IPv4 v4 = IP.fromInet4Address(inet); + IP.IPv4 mask = v4.maskWithNetworkMask(24); + + InetAddress inet1 = Inet4Address.getByName("192.168.1.55"); + v4 = IP.fromInet4Address(inet1); + IP.IPv4 masked = v4.maskWithNetworkMaskInv(24); + + IP.IPv4 test = mask.set(masked); + + InetAddress inet2 = Inet4Address.getByName("10.10.10.55"); + InetAddress inet3 = test.toInetAddress(); + Assert.assertEquals(inet2, inet3); + } +} diff --git a/core/src/test/java/net/tomp2p/peers/TestLocalMap.java b/core/src/test/java/net/tomp2p/peers/TestLocalMap.java deleted file mode 100644 index e1b70e144..000000000 --- a/core/src/test/java/net/tomp2p/peers/TestLocalMap.java +++ /dev/null @@ -1,68 +0,0 @@ -package net.tomp2p.peers; - - -import java.util.Collections; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -public class TestLocalMap { - - private PeerAddress[] addresses; - - @Rule - public TestRule watcher = new TestWatcher() { - protected void starting(Description description) { - System.out.println("Starting test: " + description.getMethodName()); - } - }; - - @Before - public void setup() { - addresses = new PeerAddress[2]; - addresses[0] = new PeerAddress(new Number160("0x5")); - addresses[1] = new PeerAddress(new Number160("0x5")); - } - - @Test - public void testMap() { - LocalMap map = new LocalMap(Number160.ZERO); - boolean added = map.peerFound(addresses[0], addresses[0]); - Assert.assertTrue(added); - boolean offline = map.peerFailed(addresses[0], null); - Assert.assertTrue(offline); - PeerStatistic addr = map.translate(addresses[1]); - Assert.assertTrue(addr == null); - } - - @Test - public void testMapMaintenance() throws InterruptedException { - LocalMap map = new LocalMap(Number160.ZERO); - boolean added = map.peerFound(addresses[0], addresses[0]); - Assert.assertTrue(added); - PeerStatistic ps = map.nextForMaintenance(Collections.emptyList()); - Assert.assertTrue(ps == null); - Thread.sleep(2100); - ps = map.nextForMaintenance(Collections.emptyList()); - Assert.assertTrue(ps != null); - - } - - @Test - public void testMapTranslate() { - LocalMap map = new LocalMap(Number160.ZERO); - boolean added = map.peerFound(addresses[0], addresses[0]); - Assert.assertTrue(added); - PeerStatistic addr = map.translate(addresses[1]); - Assert.assertTrue(addr != null); - PeerAddress old = map.translateReverse(addresses[0]); - Assert.assertTrue(old == addresses[1]); - } - - -} diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java index bbadffa13..aff2a7c20 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java @@ -153,8 +153,8 @@ public void testPeerAddress5() throws UnknownHostException { psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), true, true, true, true, - true, psa); + InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, true, + false, psa); final int length = 200; byte[] me = new byte[length]; @@ -186,7 +186,7 @@ public void testPeerAddress6() throws UnknownHostException { RND.nextInt(BIT_16), RND.nextInt(BIT_16))); PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde0"), RND.nextInt(BIT_16), - RND.nextInt(BIT_16)), true, true, true, true, true, psa); + RND.nextInt(BIT_16)), null, true, true, true, true, true, false, psa); final int length = 200; byte[] me = new byte[length]; @@ -218,7 +218,7 @@ public void testPeerAddress7() throws UnknownHostException { RND.nextInt(BIT_16), RND.nextInt(BIT_16))); PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde0"), RND.nextInt(BIT_16), - RND.nextInt(BIT_16)), true, true, true, true, true, psa); + RND.nextInt(BIT_16)), null, true, true, true, true, true, false, psa); Assert.assertEquals(142, pa3.toByteArray().length); diff --git a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java index 4e50305a8..40754d9e1 100644 --- a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java +++ b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java @@ -83,7 +83,7 @@ public static PeerAddress createAddress(Number160 idSender, String inetSender, i int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false, + PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false,false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; } diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index fe0abb130..86495f1bc 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -115,9 +115,9 @@ public void operationComplete(FutureDiscover future) throws Exception { if (future.isSuccess()) { // UPNP or NAT-PMP was // successful, set flag - peer.peerBean().serverPeerAddress(serverAddress.changePortForwarding(true)); - peer.peerBean().serverPeerAddress() - .internalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); + PeerAddress newServerAddress = serverAddress.changePortForwarding(true); + newServerAddress = newServerAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); + peer.peerBean().serverPeerAddress(newServerAddress); futureNAT.done(future.peerAddress(), future.reporter()); } else { // indicate relay diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index a201fe7de..acee5f9bc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -197,7 +197,7 @@ public static Peer init(String ip, int port, int peerId) ccc.senderTCP(InetAddress.getByName(ip)); Peer peer = new PeerBuilder(Number160.createHash(peerId)).channelClientConfiguration(ccc).ports(port).bindings(b) .start(); - System.err.println("peer"+peer.peerAddress()); + System.out.println("Init "+peer.peerAddress()); return peer; } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index df8b877a2..a339900dc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -5,16 +5,12 @@ import java.net.InetAddress; import java.util.Random; -import net.tomp2p.connection.Bindings; -import net.tomp2p.connection.ChannelClientConfiguration; -import net.tomp2p.futures.FutureAnnounce; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.futures.FuturePing; import net.tomp2p.nat.FutureNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; @@ -39,16 +35,15 @@ * @author Thomas Bocek * */ -//@Ignore +@Ignore public class TestNATLocal implements Serializable { private static final long serialVersionUID = 1L; //### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "enp0s25"; + final static private String INF = "eth1"; final static private Random RND = new Random(42); - static private Peer relayPeer = null; static private Number160 relayPeerId = new Number160(RND); @Before @@ -59,7 +54,7 @@ public void before() throws IOException, InterruptedException { @After public void after() throws IOException, InterruptedException { - //LocalNATUtils.executeNatSetup("stop", "0"); + LocalNATUtils.executeNatSetup("stop", "0"); } @@ -77,34 +72,39 @@ public void testLocalSend() throws Exception { @Override public Serializable execute() throws Exception { - System.err.println("test"); Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); put("p1", peer1); put("p2", peer2); - FutureAnnounce fa1 = peer1.localAnnounce().start().awaitUninterruptibly(); - FutureAnnounce fa2 = peer2.localAnnounce().start().awaitUninterruptibly(); - FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); FutureDiscover fd2 = peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); FutureNAT fn1 = pn1.startSetupPortforwarding(fd1).awaitUninterruptibly(); FutureNAT fn2 = pn2.startSetupPortforwarding(fd2).awaitUninterruptibly(); + StringBuilder sb = new StringBuilder(); if(fn1.isSuccess() && fn2.isSuccess()) { - // now peer1 and peer2 know each other locally. - PeerAddress punr2 = new PeerAddress(Number160.createHash(1), relayAddress.inetAddress(), - 5001, 5001); + PeerAddress punr2 = peer2.peerAddress(); + InetAddress internal = InetAddress.getByName("0.0.0.3"); + punr2 = punr2.changeInternalPeerSocketAddress(new PeerSocketAddress(internal, 5001, 5001)); + punr2 = punr2.changePortForwarding(true); FuturePing fp1 = peer1.ping().peerAddress(punr2).start().awaitUninterruptibly(); - System.err.println(fp1.failedReason() + " /" + fp1.remotePeer()); + sb.append(fp1.isSuccess()); + System.out.println(fp1.failedReason() + " /" + fp1.remotePeer()); + FuturePing fp2 = peer1.ping().tcpPing().peerAddress(punr2).start().awaitUninterruptibly(); + sb.append(fp2.isSuccess()); + System.out.println(fp1.failedReason() + " /" + fp2.remotePeer()); + sb.append(fp2.isSuccess()); + System.out.println(peer1.peerBean().peerMap().getPeerStatistic(punr2).peerAddress()); + sb.append(peer1.peerBean().peerMap().getPeerStatistic(punr2).peerAddress().inetAddress()); } else { System.err.println("failed: "+ fn1.failedReason() + fn2.failedReason()); return fn1.failedReason() + fn2.failedReason(); } - return "done"; + return sb.toString(); } }, new Command() { @@ -114,6 +114,7 @@ public Serializable execute() throws Exception { } }); unr1.waitFor(); + Assert.assertEquals("truetruetrue/172.20.0.1", unr1.getResult(0)); } finally { System.out.print("LOCAL> shutdown."); LocalNATUtils.shutdown(relayPeer); @@ -122,44 +123,4 @@ public Serializable execute() throws Exception { System.out.println("."); } } - - @Test - public void testLocal() throws Exception { -// relayPeer = null; -// Process unr1 = null; -// Process unr2 = null; -// try { -// relayPeer = LocalNATUtils.createRealNode(relayPeerId, "eth1"); -// InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); -// unr1 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "2"); -// unr2 = LocalNATUtils.executePeer(TestNATLocal.class, "0", relayAddress.getHostAddress(), "3"); -// String result1 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command announce"); -// String result2 = LocalNATUtils.waitForLineOrDie(unr2, "done", "command announce"); -// // -// -// Assert.assertEquals("1", result1); -// Assert.assertEquals("1", result2); -// -// String result3 = LocalNATUtils.waitForLineOrDie(unr1, "done", "command ping 0 3"); -// Assert.assertEquals("/10.0.0.3", result3); -// -// -// } finally { -// System.err.print("shutdown."); -// if (relayPeer != null) { -// relayPeer.shutdown().awaitUninterruptibly(); -// relayPeer = null; -// } -// System.err.print("."); -// if (unr1 != null) { -// LocalNATUtils.killPeer(unr1); -// } -// System.err.println("."); -// if (unr2 != null) { -// LocalNATUtils.killPeer(unr2); -// } -// } - } - - } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index 828a8d676..cd8ecf9be 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -16,6 +16,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; /** @@ -34,14 +35,14 @@ * @author Thomas Bocek * */ -//@Ignore +@Ignore public class TestNATTypeDetection 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 = "wlp3s0"; + final static private String INF = "eth1"; static private Number160 relayPeerId = new Number160(RND); diff --git a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java index 02600669f..178450835 100644 --- a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java +++ b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java @@ -213,7 +213,7 @@ public static PeerAddress createAddress(Number160 idSender, String inetSender, i boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false, + PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; } diff --git a/replication/src/test/java/net/tomp2p/Utils2.java b/replication/src/test/java/net/tomp2p/Utils2.java index f2237aa60..13ab3d3ca 100644 --- a/replication/src/test/java/net/tomp2p/Utils2.java +++ b/replication/src/test/java/net/tomp2p/Utils2.java @@ -85,7 +85,7 @@ public static PeerAddress createAddress(Number160 idSender, String inetSender, i int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, firewallTCP, firewallUDP, false, false, false, + PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; } From cd3ba25f4a96d5487232f0293cba290faafe14e1 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 29 Jun 2015 16:04:14 +0200 Subject: [PATCH 046/135] testcase for relays with real peers behind nat (behind same and different nat) --- .../net/tomp2p/holep/manual/TestNATRelay.java | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java new file mode 100644 index 000000000..3c96bb515 --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -0,0 +1,144 @@ +package net.tomp2p.holep.manual; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Random; + +import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerSocketAddress; + +import org.junit.After; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore +public class TestNATRelay implements Serializable { + + private static final long serialVersionUID = 1L; + final static private Random RND = new Random(42); + static private Number160 relayPeerId = new Number160(RND); + //### CHANGE THIS TO YOUR INTERFACE### + final static private String INF = "eth1"; + + @Before + public void before() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("start", "0", "sym"); + LocalNATUtils.executeNatSetup("start", "1", "sym"); + } + + @After + public void after() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("stop", "0"); + LocalNATUtils.executeNatSetup("stop", "1"); + } + + @SuppressWarnings("serial") + @Test + public void testRealRelayDifferentNAT() throws Exception { + Peer relayPeer = null; + RemotePeer unr1 = null; + RemotePeer unr2 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + //setup relay + return "tbd"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + + unr2 = LocalNATUtils.executePeer(1, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 0); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + //setup relay + return "tbd"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + unr1.waitFor(); + unr2.waitFor(); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1, unr2); + System.out.println("."); + } + } + + @SuppressWarnings("serial") + @Test + public void testRealRelaySameNAT() throws Exception { + Peer relayPeer = null; + RemotePeer unr1 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); + put("p1", peer1); + put("p2", peer2); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + FutureDiscover fd2 = peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); + //setup relay + + + return "tbd"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + return LocalNATUtils.shutdown((Peer)get("p1"), (Peer)get("p2")); + } + }); + unr1.waitFor(); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } +} From 9a351472ba69f0c992af0c9deaa4531642f6a1eb Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 5 Jul 2015 07:38:19 +0200 Subject: [PATCH 047/135] release buffer after using it, reported by Luiz Angelo Steffenel --- .../src/main/java/net/tomp2p/storage/DataSerializer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java index 0af8fdf39..2e7c66a8d 100644 --- a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java +++ b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java @@ -76,10 +76,11 @@ private void serializeFile(DataOutput out, Data value) throws IOException, FileN // store as external file, create path RandomAccessFile file = null; FileChannel rwChannel = null; + AlternativeCompositeByteBuf acb = null; try { file = new RandomAccessFile(new File(path, hash.toString()), "rw"); rwChannel = file.getChannel(); - AlternativeCompositeByteBuf acb = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); + acb = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); // store data to disk // header first value.encodeHeader(acb, signatureFactory); @@ -97,7 +98,9 @@ private void serializeFile(DataOutput out, Data value) throws IOException, FileN throw new IOException(e); } } finally { - + if (acb!=null) { + acb.release(); + } if (rwChannel != null) { rwChannel.close(); } From 7218f11378d49a262ff75651080b80e7cfa708e4 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 11 Jul 2015 22:10:18 +0200 Subject: [PATCH 048/135] adding testcase for relay, start investigating time issue --- .../net/tomp2p/relay/BaseRelayServer.java | 16 ++-- .../main/java/net/tomp2p/relay/RconRPC.java | 5 +- .../tomp2p/holep/manual/LocalNATUtils.java | 29 +++++-- .../net/tomp2p/holep/manual/TestNATRelay.java | 78 ++++++++++++++++++- 4 files changed, 105 insertions(+), 23 deletions(-) diff --git a/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java b/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java index 56dd73137..e7b320496 100644 --- a/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java +++ b/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.PeerException; @@ -52,6 +53,7 @@ public abstract class BaseRelayServer extends DispatchHandler implements PeerSta private PeerAddress unreachablePeer; private final ArrayList offlineListeners; private List> peerMap = null; + private final static AtomicLong messageCounter = new AtomicLong(); protected BaseRelayServer(Peer peer, PeerAddress unreachablePeer, RelayType relayType) { super(peer.peerBean(), peer.connectionBean()); @@ -113,15 +115,6 @@ public final Number160 relayPeerId() { @Override public final void handleResponse(Message message, PeerConnection peerConnection, boolean sign, final Responder responder) throws Exception { - // TODO the sender should have the ip/port from the relay peer, the peerId - // from the unreachable peer, in order to have 6 relays instead of 5 - handleResponse(message, responder); - } - - /** - * Receive a message at the relay server from a given peer - */ - public final void handleResponse(Message message, final Responder responder) { // special treatment for ping and neighbor if (message.command() == RPC.Commands.PING.getNr()) { LOG.debug("Received message {} to handle ping for unreachable peer {}", message, unreachablePeer); @@ -130,6 +123,7 @@ public final void handleResponse(Message message, final Responder responder) { LOG.debug("Received message {} to handle neighbor request for unreachable peer {}", message, unreachablePeer); handleNeigbhor(message, responder); } else { + messageCounter.incrementAndGet(); LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeer); FutureDone response = forwardToUnreachable(message); response.addListener(new BaseFutureAdapter>() { @@ -270,4 +264,8 @@ public final void setPeerMap(List> peerMap, Messag * @param originalMessage the original message that contained the extracted peer map */ protected abstract void peerMapUpdated(Message originalMessage, Message preparedResponse); + + public static long messageCounter() { + return messageCounter.get(); + } } diff --git a/nat/src/main/java/net/tomp2p/relay/RconRPC.java b/nat/src/main/java/net/tomp2p/relay/RconRPC.java index 64277043b..ae1255a57 100644 --- a/nat/src/main/java/net/tomp2p/relay/RconRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RconRPC.java @@ -91,13 +91,14 @@ public void handleResponse(final Message message, final PeerConnection peerConne * * @param message * @param responder + * @throws Exception */ - private void handleRconForward(final Message message, final Responder responder) { + private void handleRconForward(final Message message, final Responder responder) throws Exception { // get the relayForwarderRPC via Dispatcher to retrieve the existing peerConnection final BaseRelayServer forwarder = extractRelayForwarder(message); if (forwarder != null) { final Message forwardMessage = createForwardMessage(message, forwarder.unreachablePeerAddress()); - forwarder.handleResponse(forwardMessage, responder); + forwarder.handleResponse(forwardMessage, null, true, responder); } else { handleFail(message, responder, "No RelayForwarder registered for peerId=" + message.recipient().peerId().toString()); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index acee5f9bc..2a2e781da 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -20,6 +20,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; public class LocalNATUtils { private static final String TAG = "##BASE64##:"; @@ -94,14 +95,21 @@ public void run() { for (int i = 0; i < cmd.length; i++) { boolean done = false; while (!done) { - String line = read(process.getInputStream()).trim(); - if (line.startsWith(TAG)) { - line = line.substring(TAG.length()); - Object o = fromString(line); - results.set(i, o); - done = true; + String line = read(process.getInputStream()); + if(line != null) { + line = line.trim(); + if (line.startsWith(TAG)) { + line = line.substring(TAG.length()); + Object o = fromString(line); + results.set(i, o); + done = true; + } else { + System.out.println("OUT["+nr+"]>" + line); + } } else { - System.out.println("OUT["+nr+"]>" + line); + System.out.println("OUT["+nr+"]>null"); + cl.countDown(); + break; } } cl.countDown(); @@ -182,13 +190,18 @@ public static void handleMain(String[] args) throws ClassNotFoundException, IOEx try { Serializable result = cmd.execute(); System.out.println(TAG + LocalNATUtils.toString(result)); - } catch (Exception e) { + } catch (Throwable e) { e.printStackTrace(); + System.out.println(TAG + LocalNATUtils.toString(e.getMessage())); } } } + public static PeerAddress peerAddress(String ip, int port, int peerId) throws UnknownHostException { + return new PeerAddress(Number160.createHash(peerId), ip, port, port); + } + public static Peer init(String ip, int port, int peerId) throws UnknownHostException, IOException { Bindings b = new Bindings(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 3c96bb515..052d1e35c 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -2,16 +2,25 @@ import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; import java.util.Random; +import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.relay.BaseRelayServer; +import net.tomp2p.relay.tcp.TCPRelayClientConfig; +import net.tomp2p.rpc.ObjectDataReply; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -45,6 +54,7 @@ public void testRealRelayDifferentNAT() throws Exception { RemotePeer unr2 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + PeerNAT rn1 = new PeerBuilderNAT(relayPeer).start(); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); unr1 = LocalNATUtils.executePeer(0, new Command() { @@ -56,6 +66,28 @@ public Serializable execute() throws Exception { FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); //setup relay + FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); + + Assert.assertTrue(frn1.isSuccess()); + + peer1.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me1"; + } + }); + //TODO: this is wrong here to pass the testcase find out why + Thread.sleep(1000); + PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.1.2", 5000, 1); + Collection psa = new ArrayList(); + psa.add(relayAddress); + peer2 = peer2.changePeerSocketAddresses(psa); + peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); + FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + System.out.println(fdir1.failedReason()); + Assert.assertTrue(fdir1.isSuccess()); + Assert.assertEquals("me2", fdir1.object()); + return "tbd"; } }, new Command() { @@ -71,11 +103,34 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 0); + Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 1); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); //setup relay + FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); + System.out.println(frn1.failedReason()); + + Assert.assertTrue(frn1.isSuccess()); + + peer1.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me2"; + } + }); + //TODO: this is wrong here to pass the testcase find out why + Thread.sleep(1000); + PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.0.2", 5000, 0); + Collection psa = new ArrayList(); + psa.add(relayAddress); + peer2 = peer2.changePeerSocketAddresses(psa); + peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); + FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + System.out.println(fdir1.failedReason()); + Assert.assertTrue(fdir1.isSuccess()); + Assert.assertEquals("me1", fdir1.object()); + return "tbd"; } }, new Command() { @@ -104,6 +159,7 @@ public void testRealRelaySameNAT() throws Exception { RemotePeer unr1 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + PeerNAT rn1 = new PeerBuilderNAT(relayPeer).start(); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); unr1 = LocalNATUtils.executePeer(0, new Command() { @@ -120,9 +176,23 @@ public Serializable execute() throws Exception { PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); //setup relay - - - return "tbd"; + FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); + FutureRelayNAT frn2 = pn2.startRelay(new TCPRelayClientConfig(), fd2).awaitUninterruptibly(); + System.out.println(frn1.failedReason()); + Assert.assertTrue(frn1.isSuccess()); + Assert.assertTrue(frn2.isSuccess()); + //send message from p1 to p2 + peer2.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me"; + } + }); + FutureDirect fdir1 = peer1.sendDirect(peer2.peerAddress()).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("me", fdir1.object()); + //should be direct not over relay + Assert.assertEquals(0, BaseRelayServer.messageCounter()); + return "done"; } }, new Command() { From 74ddf0c9019bc16dc44bda9f47fe9d7384d9735c Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 19 Jul 2015 21:21:02 +0200 Subject: [PATCH 049/135] work log - 18.7.2015 10:45 - investigate testcase that fails in testRealRelayDifferentNAT() 11:25 / 40min 11:40 - added testcases for ConcurrentCacheSet 11:45 / 5min 11:45 - refactoring distributedrelay 11:55 / 10min 13:00 - refactoring distributedrelay 14:35 / 95min 15:25 - continunig refactoring distributedrelay, peernat and peernatbuilder 16:00 / 35min 17:10 - make testcases run again, debugging 18:10 / 60min --- .../net/tomp2p/utils}/ConcurrentCacheSet.java | 43 +-- ...Cache.java => TestConcurrentCacheMap.java} | 2 +- .../tomp2p/utils/TestConcurrentCacheSet.java | 43 +++ .../java/net/tomp2p/nat/FutureRelayNAT.java | 14 - .../java/net/tomp2p/nat/PeerBuilderNAT.java | 78 +++- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 212 +++-------- .../net/tomp2p/relay/DistributedRelay.java | 351 ++++++------------ .../main/java/net/tomp2p/relay/Forwarder.java | 176 +++++++++ .../{FutureRelay.java => FutureRelay.jav} | 0 .../net/tomp2p/relay/PeerMapUpdateTask.java | 64 +--- .../java/net/tomp2p/relay/RelayCallback.java | 12 + .../main/java/net/tomp2p/relay/RelayRPC.java | 164 ++++++-- .../net/tomp2p/holep/manual/TestNATLocal.java | 4 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 42 ++- nat/src/test/resources/logback.xml | 3 + 15 files changed, 670 insertions(+), 538 deletions(-) rename {nat/src/main/java/net/tomp2p/relay => core/src/main/java/net/tomp2p/utils}/ConcurrentCacheSet.java (58%) rename core/src/test/java/net/tomp2p/utils/{TestCache.java => TestConcurrentCacheMap.java} (99%) create mode 100644 core/src/test/java/net/tomp2p/utils/TestConcurrentCacheSet.java create mode 100644 nat/src/main/java/net/tomp2p/relay/Forwarder.java rename nat/src/main/java/net/tomp2p/relay/{FutureRelay.java => FutureRelay.jav} (100%) create mode 100644 nat/src/main/java/net/tomp2p/relay/RelayCallback.java diff --git a/nat/src/main/java/net/tomp2p/relay/ConcurrentCacheSet.java b/core/src/main/java/net/tomp2p/utils/ConcurrentCacheSet.java similarity index 58% rename from nat/src/main/java/net/tomp2p/relay/ConcurrentCacheSet.java rename to core/src/main/java/net/tomp2p/utils/ConcurrentCacheSet.java index ce738dabe..fdd4e6d62 100644 --- a/nat/src/main/java/net/tomp2p/relay/ConcurrentCacheSet.java +++ b/core/src/main/java/net/tomp2p/utils/ConcurrentCacheSet.java @@ -1,16 +1,16 @@ -package net.tomp2p.relay; +package net.tomp2p.utils; import java.util.Collection; import java.util.Iterator; import java.util.Map; +import java.util.Objects; import java.util.Set; -import net.tomp2p.utils.ConcurrentCacheMap; - /** * Wrapper of {@link ConcurrentCacheMap} * * @author Raphael Voellmy + * @author Thomas Bocek * * @param */ @@ -22,27 +22,26 @@ public ConcurrentCacheSet() { map = new ConcurrentCacheMap(); } - public ConcurrentCacheSet(int timeToLive) { - map = new ConcurrentCacheMap(timeToLive, ConcurrentCacheMap.MAX_ENTRIES); + public ConcurrentCacheSet(final int timeToLiveSeconds) { + map = new ConcurrentCacheMap(timeToLiveSeconds, ConcurrentCacheMap.MAX_ENTRIES); } - public ConcurrentCacheSet(int timeToLive, int maxEntries) { - map = new ConcurrentCacheMap(timeToLive, maxEntries); + public ConcurrentCacheSet(final int timeToLiveSeconds, final int maxEntries) { + map = new ConcurrentCacheMap(timeToLiveSeconds, maxEntries); } - public ConcurrentCacheSet(int timeToLive, int maxEntries, boolean refreshTimeout) { - map = new ConcurrentCacheMap(timeToLive, maxEntries, refreshTimeout); + public ConcurrentCacheSet(final int timeToLiveSeconds, final int maxEntries, final boolean refreshTimeout) { + map = new ConcurrentCacheMap(timeToLiveSeconds, maxEntries, refreshTimeout); } @Override - public boolean add(E e) { - boolean alreadyContained = !map.containsKey(e); - map.put(e, false); - return alreadyContained; + public boolean add(final E e) { + final Boolean retVal = map.put(e, true); + return Objects.equals(retVal, Boolean.TRUE); } @Override - public boolean addAll(Collection c) { + public boolean addAll(final Collection c) { boolean changed = false; for(E o : c) { changed |= add(o); @@ -56,12 +55,12 @@ public void clear() { } @Override - public boolean contains(Object o) { + public boolean contains(final Object o) { return map.keySet().contains(o); } @Override - public boolean containsAll(Collection c) { + public boolean containsAll(final Collection c) { return map.keySet().containsAll(c); } @@ -76,15 +75,13 @@ public Iterator iterator() { } @Override - public boolean remove(Object o) { + public boolean remove(final Object o) { return map.remove(o) != null; } @Override - public boolean removeAll(Collection c) { - //TODO: type safety? - @SuppressWarnings("unchecked") - Iterator it = (Iterator) c.iterator(); + public boolean removeAll(final Collection c) { + final Iterator it = (Iterator) c.iterator(); boolean changed = false; while(it.hasNext()) { changed |= remove(it.next()); @@ -94,9 +91,7 @@ public boolean removeAll(Collection c) { @Override public boolean retainAll(Collection c) { - Set diff = map.keySet(); - diff.removeAll(c); - return removeAll(diff); + throw new UnsupportedOperationException(); } @Override diff --git a/core/src/test/java/net/tomp2p/utils/TestCache.java b/core/src/test/java/net/tomp2p/utils/TestConcurrentCacheMap.java similarity index 99% rename from core/src/test/java/net/tomp2p/utils/TestCache.java rename to core/src/test/java/net/tomp2p/utils/TestConcurrentCacheMap.java index 36bdf6028..1876b3fcc 100644 --- a/core/src/test/java/net/tomp2p/utils/TestCache.java +++ b/core/src/test/java/net/tomp2p/utils/TestConcurrentCacheMap.java @@ -31,7 +31,7 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; -public class TestCache { +public class TestConcurrentCacheMap { @Rule public TestRule watcher = new TestWatcher() { diff --git a/core/src/test/java/net/tomp2p/utils/TestConcurrentCacheSet.java b/core/src/test/java/net/tomp2p/utils/TestConcurrentCacheSet.java new file mode 100644 index 000000000..10c6ff5cd --- /dev/null +++ b/core/src/test/java/net/tomp2p/utils/TestConcurrentCacheSet.java @@ -0,0 +1,43 @@ +package net.tomp2p.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class TestConcurrentCacheSet { + + @Test + public void testCache1() throws InterruptedException { + ConcurrentCacheSet ccs = new ConcurrentCacheSet(1); + ccs.add("test"); + Assert.assertTrue(ccs.contains("test")); + Thread.sleep(1001); + Assert.assertFalse(ccs.contains("test")); + } + + @Test + public void testCache2() throws InterruptedException { + ConcurrentCacheSet ccs = new ConcurrentCacheSet(1); + ccs.add("test1"); + ccs.add("test2"); + + List tmp = new ArrayList(); + tmp.add("test1"); + + ccs.removeAll(tmp); + Assert.assertTrue(ccs.contains("test2")); + Thread.sleep(1001); + Assert.assertEquals(0, ccs.size()); + } + + @Test + public void testCache3() throws InterruptedException { + ConcurrentCacheSet ccs = new ConcurrentCacheSet(1); + ccs.add("test1"); + ccs.add("test2"); + ccs.clear(); + Assert.assertEquals(0, ccs.size()); + } +} diff --git a/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java b/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java index a8a11f91d..115155185 100644 --- a/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java @@ -3,13 +3,11 @@ import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureImpl; import net.tomp2p.p2p.Shutdown; -import net.tomp2p.relay.FutureRelay; import net.tomp2p.relay.buffer.BufferRequestListener; public class FutureRelayNAT extends BaseFutureImpl { private Shutdown shutdown; - private FutureRelay futureRelay; private BufferRequestListener bufferRequestListener; public FutureRelayNAT() { @@ -50,18 +48,6 @@ public Shutdown shutdown() { } } - public FutureRelayNAT futureRelay(FutureRelay futureRelay) { - synchronized (lock) { - this.futureRelay = futureRelay; - } - return this; - } - - public FutureRelay futureRelay() { - synchronized (lock) { - return futureRelay; - } - } public FutureRelayNAT bufferRequestListener(BufferRequestListener bufferRequestListener) { this.bufferRequestListener = bufferRequestListener; diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index 473601e09..bf747deb5 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -2,28 +2,57 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.FutureDone; import net.tomp2p.holep.HolePInitiatorImpl; import net.tomp2p.holep.HolePRPC; +import net.tomp2p.message.Message; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.Shutdown; +import net.tomp2p.p2p.builder.BootstrapBuilder; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.relay.BaseRelayClient; +import net.tomp2p.relay.DistributedRelay; import net.tomp2p.relay.RconRPC; +import net.tomp2p.relay.RelayCallback; +import net.tomp2p.relay.RelayClientConfig; import net.tomp2p.relay.RelayRPC; import net.tomp2p.relay.RelayServerConfig; import net.tomp2p.relay.RelayType; +import net.tomp2p.relay.tcp.TCPRelayClientConfig; import net.tomp2p.relay.tcp.TCPRelayServerConfig; public class PeerBuilderNAT { private static final Logger LOG = LoggerFactory.getLogger(PeerBuilderNAT.class); + private static final RelayCallback DEFAULT_RELAY_CALLBACK = new RelayCallback() { + + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} + }; + final private Peer peer; private boolean manualPorts = false; + + private Boolean relayMaintenance; + + private RelayClientConfig relayConfig; + + private RelayCallback relayCallback; + + private BootstrapBuilder bootstrapBuilder; + + private Integer peerMapUpdateIntervalSeconds; // holds multiple implementations for serving relay peers private Map relayServerConfigurations; @@ -121,8 +150,47 @@ public PeerBuilderNAT holePNumberOfHolePunches(final int holePNumberOfPunches) { public int holePNumberOfPunches() { return holePNumberOfPunches; } + + public RelayClientConfig relayConfig() { + return relayConfig; + } + + public PeerBuilderNAT relayConfig(RelayClientConfig relayConfig) { + this.relayConfig = relayConfig; + return this; + } + + public RelayCallback relayCallback() { + return relayCallback; + } + + public PeerBuilderNAT relayCallback(RelayCallback relayCallback) { + this.relayCallback = relayCallback; + return this; + } public PeerNAT start() { + + if(relayConfig == null) { + relayConfig = new TCPRelayClientConfig(); + } + + if(relayCallback == null) { + relayCallback = DEFAULT_RELAY_CALLBACK; + } + + if(relayMaintenance == null) { + relayMaintenance = true; + } + + if(bootstrapBuilder == null) { + bootstrapBuilder = peer.bootstrap(); + } + + if(peerMapUpdateIntervalSeconds == null) { + peerMapUpdateIntervalSeconds = 60; + } + final NATUtils natUtils = new NATUtils(); final RconRPC rconRPC = new RconRPC(peer); final HolePRPC holePunchRPC = new HolePRPC(peer); @@ -140,6 +208,14 @@ public PeerNAT start() { } } final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC, relayServerConfigurations); + + + + DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig); + + + + peer.addShutdownListener(new Shutdown() { @Override @@ -149,6 +225,6 @@ public BaseFuture shutdown() { } }); - return new PeerNAT(peer, natUtils, relayRPC, manualPorts); + return new PeerNAT(peer, natUtils, relayRPC, manualPorts, distributedRelay, relayMaintenance, relayCallback, bootstrapBuilder, peerMapUpdateIntervalSeconds); } } diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index 86495f1bc..6a883cb3b 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -7,12 +7,10 @@ import net.tomp2p.connection.Ports; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; -import net.tomp2p.holep.HolePInitiatorImpl; import net.tomp2p.message.Message; import net.tomp2p.message.Message.Type; import net.tomp2p.natpmp.NatPmpException; @@ -22,10 +20,8 @@ import net.tomp2p.p2p.builder.DiscoverBuilder; import net.tomp2p.peers.PeerAddress; import net.tomp2p.relay.DistributedRelay; -import net.tomp2p.relay.FutureRelay; import net.tomp2p.relay.PeerMapUpdateTask; -import net.tomp2p.relay.RelayClientConfig; -import net.tomp2p.relay.RelayListener; +import net.tomp2p.relay.RelayCallback; import net.tomp2p.relay.RelayRPC; import net.tomp2p.relay.RelayUtils; import net.tomp2p.rpc.RPC; @@ -41,11 +37,23 @@ public class PeerNAT { private final NATUtils natUtils; private final RelayRPC relayRPC; private final boolean manualPorts; - public PeerNAT(Peer peer, NATUtils natUtils, RelayRPC relayRPC, boolean manualPorts) { + private final DistributedRelay distributedRelay; + private final RelayCallback relayCallback; + private boolean relayMaintenance; + private BootstrapBuilder bootstrapBuilder; + private int peerMapUpdateIntervalSeconds; + + PeerNAT(Peer peer, NATUtils natUtils, RelayRPC relayRPC, boolean manualPorts, DistributedRelay distributedRelay, + boolean relayMaintenance, RelayCallback relayCallback, BootstrapBuilder bootstrapBuilder, int peerMapUpdateIntervalSeconds) { this.peer = peer; this.natUtils = natUtils; this.relayRPC = relayRPC; this.manualPorts = manualPorts; + this.distributedRelay = distributedRelay; + this.relayMaintenance = relayMaintenance; + this.relayCallback = relayCallback; + this.bootstrapBuilder = bootstrapBuilder; + this.peerMapUpdateIntervalSeconds = peerMapUpdateIntervalSeconds; } public Peer peer() { @@ -64,9 +72,9 @@ public boolean isManualPorts() { return manualPorts; } - public FutureNAT startSetupPortforwarding(final FutureDiscover futureDiscover) { + public FutureNAT portForwarding(final FutureDiscover futureDiscover) { DiscoverBuilder builder = new DiscoverBuilder(peer); - return startSetupPortforwarding(futureDiscover, builder); + return portForwarding(futureDiscover, builder); } /** @@ -81,7 +89,7 @@ public FutureNAT startSetupPortforwarding(final FutureDiscover futureDiscover) { * if UPNP or NATPMP could be setup and then you are reachable * (success), or if it failed. */ - public FutureNAT startSetupPortforwarding(final FutureDiscover futureDiscover, final DiscoverBuilder builder) { + public FutureNAT portForwarding(final FutureDiscover futureDiscover, final DiscoverBuilder builder) { final FutureNAT futureNAT = new FutureNAT(); futureDiscover.addListener(new BaseFutureAdapter() { @@ -190,167 +198,53 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { } return null; } - - private DistributedRelay startSetupRelay(FutureRelay futureRelay, final RelayClientConfig relayConfig) { - final DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig); - // close the relay connection when the peer is shutdown - peer.addShutdownListener(new Shutdown() { + + public Shutdown relay() { + distributedRelay.setupRelays(relayCallback); + + final Shutdown shutdownRelay = new Shutdown() { @Override public BaseFuture shutdown() { return distributedRelay.shutdown(); } - }); - - // open new relay when one failed - distributedRelay.addRelayListener(new RelayListener() { - @Override - public void relayFailed(PeerAddress relayAddress) { - // one failed, add new one - final FutureRelay futureRelay2 = new FutureRelay(); - distributedRelay.setupRelays(futureRelay2); - peer.notifyAutomaticFutures(futureRelay2); - } - }); - - distributedRelay.setupRelays(futureRelay); - return distributedRelay; - } - - private Shutdown startRelayMaintenance(final FutureRelay futureRelay, BootstrapBuilder bootstrapBuilder, - DistributedRelay distributedRelay, int peerMapUpdateInterval) { - final PeerMapUpdateTask peerMapUpdateTask = new PeerMapUpdateTask(relayRPC, bootstrapBuilder, distributedRelay); - peer.connectionBean().timer() - .scheduleAtFixedRate(peerMapUpdateTask, 0, peerMapUpdateInterval, TimeUnit.SECONDS); - - final Shutdown shutdown = new Shutdown() { - @Override - public BaseFuture shutdown() { - peerMapUpdateTask.cancel(); - return new FutureDone().done(); - } }; - peer.addShutdownListener(shutdown); - - return new Shutdown() { - @Override - public BaseFuture shutdown() { - peerMapUpdateTask.cancel(); - peer.removeShutdownListener(shutdown); - return new FutureDone().done(); - } - }; - } - - public FutureRelayNAT startRelay(final RelayClientConfig relayConfig, final PeerAddress peerAddress) { - final BootstrapBuilder bootstrapBuilder = peer.bootstrap().peerAddress(peerAddress); - - ((HolePInitiatorImpl) peer.peerBean().holePunchInitiator()).checkNatType(peerAddress); + peer.addShutdownListener(shutdownRelay); - return startRelay(relayConfig, bootstrapBuilder); - } - - public FutureRelayNAT startRelay(final RelayClientConfig relayConfig, BootstrapBuilder bootstrapBuilder) { - // check NAT type for possible Hole Punch - if (bootstrapBuilder.bootstrapTo() != null) { - PeerAddress[] peerAddresses = bootstrapBuilder.bootstrapTo().toArray(new PeerAddress[bootstrapBuilder.bootstrapTo().size()]); - if (peerAddresses.length > 0) { - ((HolePInitiatorImpl) peer.peerBean().holePunchInitiator()).checkNatType(peerAddresses[0]); - } - } - - final FutureRelayNAT futureBootstrapNAT = new FutureRelayNAT(); - return startRelay(relayConfig, futureBootstrapNAT, bootstrapBuilder); - } - - public FutureRelayNAT startRelay(final RelayClientConfig relayConfig, final FutureDiscover futureDiscover) { - return startRelay(relayConfig, futureDiscover, null); - } - - public FutureRelayNAT startRelay(final RelayClientConfig relayConfig, final FutureDiscover futureDiscover, final FutureNAT futureNAT) { - final FutureRelayNAT futureRelayNAT = new FutureRelayNAT(); - futureDiscover.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureDiscover future) throws Exception { - if (future.isFailed()) { - if (futureNAT != null) { - handleFutureNat(relayConfig, futureDiscover.reporter(), futureNAT, futureRelayNAT); - } else { - BootstrapBuilder bootstrapBuilder = peer.bootstrap().peerAddress(futureDiscover.reporter()); - startRelay(relayConfig, futureRelayNAT, bootstrapBuilder); - } - } else { - futureRelayNAT.done(); + if(relayMaintenance) { + final PeerMapUpdateTask peerMapUpdateTask = new PeerMapUpdateTask(relayRPC, bootstrapBuilder, distributedRelay); + peer.connectionBean().timer() + .scheduleAtFixedRate(peerMapUpdateTask, 0, peerMapUpdateIntervalSeconds, TimeUnit.SECONDS); + + final Shutdown shutdownTask = new Shutdown() { + @Override + public BaseFuture shutdown() { + peerMapUpdateTask.cancel(); + return new FutureDone().done(); } - } - }); - return futureRelayNAT; - } - - private void handleFutureNat(final RelayClientConfig relayConfig, final PeerAddress peerAddress, final FutureNAT futureNAT, - final FutureRelayNAT futureRelayNAT) { - futureNAT.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureNAT future) throws Exception { - if (future.isSuccess()) { - // setup UPNP or NATPMP worked - futureRelayNAT.done(); - } else { - BootstrapBuilder bootstrapBuilder = peer.bootstrap().peerAddress(peerAddress); - startRelay(relayConfig, futureRelayNAT, bootstrapBuilder); + }; + peer.addShutdownListener(shutdownTask); + + return new Shutdown() { + @Override + public BaseFuture shutdown() { + peer.removeShutdownListener(shutdownTask); + peer.removeShutdownListener(shutdownRelay); + peerMapUpdateTask.cancel(); + return distributedRelay.shutdown(); } - } - }); - } - - private FutureRelayNAT startRelay(final RelayClientConfig relayConfig, final FutureRelayNAT futureRelayNAT, final BootstrapBuilder bootstrapBuilder) { - PeerAddress upa = peer.peerBean().serverPeerAddress(); - upa = upa.changeFirewalledTCP(true).changeFirewalledUDP(true).changeSlow(relayConfig.type().isSlow()); - peer.peerBean().serverPeerAddress(upa); - - // find neighbors - FutureBootstrap futureBootstrap = bootstrapBuilder.start(); - futureBootstrap.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureBootstrap future) throws Exception { - if (future.isSuccess()) { - // setup relay - LOG.debug("bootstrap completed"); - final FutureRelay futureRelay = new FutureRelay(); - final DistributedRelay distributedRelay = startSetupRelay(futureRelay, relayConfig); - futureRelayNAT.bufferRequestListener(distributedRelay); - futureRelayNAT.futureRelay(futureRelay); - futureRelay.addListener(new BaseFutureAdapter() { - - @Override - public void operationComplete(FutureRelay future) throws Exception { - if (future.isSuccess()) { - // find neighbors again - FutureBootstrap futureBootstrap = bootstrapBuilder.start(); - futureBootstrap.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureBootstrap future) throws Exception { - if (future.isSuccess()) { - Shutdown shutdown = startRelayMaintenance(futureRelay, bootstrapBuilder, - distributedRelay, relayConfig.peerMapUpdateInterval()); - futureRelayNAT.done(shutdown); - } else { - futureRelayNAT.failed("2nd FutureBootstrap failed", future); - } - } - }); - } else { - futureRelayNAT.failed("FutureRelay failed", future); - } - } - }); - } else { - futureRelayNAT.failed("FutureBootstrap failed", future); + }; + } else { + return new Shutdown() { + @Override + public BaseFuture shutdown() { + peer.removeShutdownListener(shutdownRelay); + return distributedRelay.shutdown(); } - } - }); - return futureRelayNAT; + }; + } } + /** * This Method creates a {@link PeerConnection} to an unreachable (behind a * NAT) peer using an active relay of the unreachable peer. The connection diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 0ba18c5ca..715cedcf1 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -3,9 +3,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReferenceArray; import net.tomp2p.connection.PeerConnection; @@ -14,6 +18,7 @@ import net.tomp2p.futures.FutureForkJoin; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; +import net.tomp2p.futures.Futures; import net.tomp2p.message.Message; import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; @@ -22,6 +27,7 @@ import net.tomp2p.relay.buffer.BufferRequestListener; import net.tomp2p.relay.buffer.BufferedRelayClient; import net.tomp2p.rpc.RPC; +import net.tomp2p.utils.ConcurrentCacheSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,18 +41,23 @@ * @author Nico Rutishauser * */ -public class DistributedRelay implements BufferRequestListener { +public class DistributedRelay /*implements BufferRequestListener*/ { private final static Logger LOG = LoggerFactory.getLogger(DistributedRelay.class); private final Peer peer; private final RelayRPC relayRPC; - private final List relayClients; + //private final List relayClients; private final Set failedRelays; + private final Map activeClients; - private final Collection relayListeners; + //private final Collection relayListeners; private final RelayClientConfig relayConfig; + + private FutureDone shutdownFuture = new FutureDone(); + + private volatile boolean shutdown = false; /** * @param peer @@ -65,9 +76,9 @@ public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig re this.relayRPC = relayRPC; this.relayConfig = relayConfig; - relayClients = Collections.synchronizedList(new ArrayList()); + activeClients = Collections.synchronizedMap(new HashMap()); failedRelays = new ConcurrentCacheSet(relayConfig.failedRelayWaitTime()); - relayListeners = Collections.synchronizedList(new ArrayList(1)); + //relayListeners = Collections.synchronizedList(new ArrayList(1)); } public RelayClientConfig relayConfig() { @@ -79,33 +90,32 @@ public RelayClientConfig relayConfig() { * * @return List of PeerAddresses of the relay peers (copy) */ - public List relayClients() { - synchronized (relayClients) { + public Map activeClients() { + synchronized (activeClients) { // make a copy - return Collections.unmodifiableList(new ArrayList(relayClients)); + return Collections.unmodifiableMap(new HashMap(activeClients)); } } - public void addRelayListener(RelayListener relayListener) { + /*public void addRelayListener(RelayListener relayListener) { synchronized (relayListeners) { relayListeners.add(relayListener); } - } + }*/ - public FutureForkJoin> shutdown() { - final AtomicReferenceArray> futureDones; - synchronized (relayClients) { - futureDones = new AtomicReferenceArray>(relayClients.size()); - for (int i = 0; i < relayClients.size(); i++) { - futureDones.set(i, relayClients.get(i).shutdown()); + public FutureDone shutdown() { + shutdown = true; + synchronized (activeClients) { + for (Map.Entry entry: activeClients.entrySet()) { + entry.getValue().close(); } } - synchronized (relayListeners) { + /*synchronized (relayListeners) { relayListeners.clear(); - } + }*/ - return new FutureForkJoin>(futureDones); + return shutdownFuture; } /** @@ -116,7 +126,12 @@ public FutureForkJoin> shutdown() { * * @return RelayFuture containing a {@link DistributedRelay} instance */ - public FutureRelay setupRelays(final FutureRelay futureRelay) { + public DistributedRelay setupRelays(final RelayCallback relayCallback) { + startConnectionsOpen(relayCallback); + return this; + } + + private List relayCandidates() { final List relayCandidates; if (relayConfig.manualRelays().isEmpty()) { // Get the neighbors of this peer that could possibly act as relays. Relay @@ -131,235 +146,102 @@ public FutureRelay setupRelays(final FutureRelay futureRelay) { relayCandidates = new ArrayList(relayConfig.manualRelays()); } - filterRelayCandidates(relayCandidates); - setupPeerConnections(futureRelay, relayCandidates); - return futureRelay; - } - - /** - * Remove recently failed relays, peers that are relayed themselves and - * peers that are already relays - */ - private void filterRelayCandidates(Collection relayCandidates) { + //filterRelayCandidates for (Iterator iterator = relayCandidates.iterator(); iterator.hasNext();) { - PeerAddress pa = iterator.next(); + PeerAddress candidate = iterator.next(); // filter peers that are relayed themselves - if (pa.isRelayed()) { + if (candidate.isRelayed()) { iterator.remove(); continue; } - // filter relays that are already connected - synchronized (relayClients) { - for (BaseRelayClient relay : relayClients) { - if (relay.relayAddress().equals(pa)) { - iterator.remove(); - break; - } - } - } - } - - LOG.trace("Found {} addtional relay candidates", relayCandidates.size()); - } - - /** - * Sets up N peer connections to relay candidates, where N is maxRelays - * minus the current relay count. - - * @return FutureDone - */ - private void setupPeerConnections(final FutureRelay futureRelay, List relayCandidates) { - final int nrOfRelays = Math.min(relayConfig.type().maxRelayCount() - relayClients.size(), relayCandidates.size()); - if (nrOfRelays > 0) { - LOG.debug("Setting up {} relays", nrOfRelays); - - @SuppressWarnings("unchecked") - FutureDone[] futureDones = new FutureDone[nrOfRelays]; - AtomicReferenceArray> relayConnectionFutures = new AtomicReferenceArray>( - futureDones); - setupPeerConnectionsRecursive(relayConnectionFutures, relayCandidates, nrOfRelays, futureRelay, 0, new StringBuilder()); - } else { - if (relayCandidates.isEmpty()) { - // no candidates - futureRelay.failed("done"); - } else { - // nothing to do - futureRelay.done(Collections. emptyList()); + // Remove recently failed relays, peers that are relayed themselves and + // peers that are already relays + if (activeClients.containsKey(candidate)) { + iterator.remove(); } } + LOG.trace("Found {} addtional relay candidates: {}", relayCandidates.size(), relayCandidates); + + return relayCandidates; } - + + final AtomicInteger activity = new AtomicInteger(0); + /** - * Sets up connections to relay peers recursively. If the maximum number of - * relays is already reached, this method will do nothing. - * - * @param futureRelayConnections - * @param relayCandidates - * List of peers that could act as relays - * @param numberOfRelays - * The number of relays to establish. - * @param futureDone - * @return - * @throws InterruptedException + * The relay setup is called sequentially until the number of max relays is reached. If a peerconnection goes down, it will search for other relays + * @param relayCallback */ - private void setupPeerConnectionsRecursive(final AtomicReferenceArray> futures, - final List relayCandidates, final int numberOfRelays, final FutureRelay futureRelay, - final int fail, final StringBuilder status) { - int active = 0; - for (int i = 0; i < numberOfRelays; i++) { - if (futures.get(i) == null) { - PeerAddress candidate = null; - synchronized (relayCandidates) { - if (!relayCandidates.isEmpty()) { - candidate = relayCandidates.remove(0); - } - } - if (candidate != null) { - // contact the candiate and ask for being my relay - FutureDone futureDone = sendMessage(candidate); - futures.set(i, futureDone); - active++; - } - } else { - active++; + private void startConnectionsOpen(final RelayCallback relayCallback) { + + synchronized (activeClients) { + if(activity.incrementAndGet() == 1 && shutdown && activeClients.isEmpty()) { + shutdownFuture.done(); + LOG.debug("shutting down, don't restart relays"); + return; } } - if (active == 0) { - updatePeerAddress(); - futureRelay.failed("No candidates: " + status.toString()); + + if(activeClients.size() >= relayConfig.type().maxRelayCount()) { + LOG.debug("we have enough relays"); return; - } else if (fail > relayConfig.maxFail()) { - updatePeerAddress(); - futureRelay.failed("Maxfail: " + status.toString()); + } + + //get candidates + final List relayCandidates = relayCandidates(); + if(relayCandidates.isEmpty()) { + LOG.debug("no more relays"); return; } - - FutureForkJoin> ffj = new FutureForkJoin>(active, false, - futures); - ffj.addListener(new BaseFutureAdapter>>() { - public void operationComplete(FutureForkJoin> futureForkJoin) throws Exception { - if (futureForkJoin.isSuccess()) { - updatePeerAddress(); - futureRelay.done(relayClients()); - } else if (!peer.isShutdown()) { - setupPeerConnectionsRecursive(futures, relayCandidates, numberOfRelays, futureRelay, fail + 1, - status.append(futureForkJoin.failedReason()).append(" ")); - } else { - futureRelay.failed(futureForkJoin); - } - } - }); - } - - /** - * Send the setup-message to the relay peer. If the peer that is asked to act as - * relay is relayed itself, the request will be denied. - * - * @param candidate the relay's peer address - * @param relayConfig - * @return FutureDone with a peer connection to the newly set up relay peer - */ - private FutureDone sendMessage(final PeerAddress candidate) { - final FutureDone futureDone = new FutureDone(); - - final Message message = relayRPC.createMessage(candidate, RPC.Commands.RELAY.getNr(), Type.REQUEST_1); - - // depend on the relay type whether to keep the connection open or close it after the setup. - message.keepAlive(relayConfig.type().keepConnectionOpen()); - - // encode the relay type in the message such that the relay node knows how to handle - message.intValue(relayConfig.type().ordinal()); - - // append relay-type specific data - relayConfig.prepareSetupMessage(message); - - LOG.debug("Setting up relay connection to peer {}, message {}", candidate, message); - final FuturePeerConnection fpc = peer.createPeerConnection(candidate); - fpc.addListener(new BaseFutureAdapter() { - public void operationComplete(final FuturePeerConnection futurePeerConnection) throws Exception { - if (futurePeerConnection.isSuccess()) { - // successfully created a connection to the relay peer - final PeerConnection peerConnection = futurePeerConnection.object(); - - // send the message - FutureResponse response = RelayUtils.send(peerConnection, peer.peerBean(), peer.connectionBean(), message); - response.addListener(new BaseFutureAdapter() { - public void operationComplete(FutureResponse future) throws Exception { - if (future.isSuccess()) { - // finialize the relay setup - setupAddRelays(peerConnection); - futureDone.done(peerConnection); - } else { - LOG.debug("Peer {} denied relay request", candidate); - failedRelays.add(candidate); - futureDone.failed(future); + + final PeerAddress candidate = relayCandidates.get(0); + final FutureDone futureDone = relayRPC.sendSetupMessage(candidate, relayConfig); + futureDone.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(final FutureDone future) + throws Exception { + + if(future.isSuccess()) { + synchronized (activeClients) { + activeClients.put(candidate, future.object()); + updatePeerAddress(); + } + LOG.debug("found relay: {}", candidate); + relayCallback.onRelayAdded(candidate, future.object()); + startConnectionsOpen(relayCallback); + + future.object().closeFuture().addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(final FutureDone futureClose) + throws Exception { + failedRelays.add(future.object().remotePeer()); + synchronized (activeClients) { + activeClients.remove(candidate, future.object()); + updatePeerAddress(); } + LOG.debug("lost/offline relay: {}", candidate); + relayCallback.onRelayRemoved(candidate, future.object()); + startConnectionsOpen(relayCallback); } }); } else { - LOG.debug("Unable to setup a connection to relay peer {}", candidate); - failedRelays.add(candidate); - futureDone.failed(futurePeerConnection); + synchronized (activeClients) { + activeClients.remove(candidate, future.object()); + updatePeerAddress(); + } + LOG.debug("bad relay: {}", candidate); + relayCallback.onRelayRemoved(candidate, future.object()); + startConnectionsOpen(relayCallback); } - } - }); - - return futureDone; - } - - /** - * Is called when the setup with the relay worked. Adds the relay to the list. - */ - private void setupAddRelays(PeerConnection peerConnection) { - synchronized (relayClients) { - if (relayClients.size() >= relayConfig.type().maxRelayCount()) { - LOG.warn("The maximum number ({}) of relays is reached", relayConfig.type().maxRelayCount()); - return; - } - } - - BaseRelayClient connection = relayConfig.createClient(peerConnection, peer); - addCloseListener(connection); - - synchronized (relayClients) { - LOG.debug("Adding peer {} as a relay", peerConnection.remotePeer()); - relayClients.add(connection); - relayRPC.addClient(connection); - } - } - - /** - * Adds a close listener for an open peer connection, so that if the - * connection to the relay peer drops, a new relay is found and a new relay - * connection is established - * - * @param connection - * the relay connection on which to add a close listener - */ - private void addCloseListener(final BaseRelayClient connection) { - connection.addCloseListener(new RelayListener() { - @Override - public void relayFailed(PeerAddress relayAddress) { - // used to remove a relay peer from the unreachable peers - // peer address. It will not cut the - // connection to an existing peer, but only update the - // unreachable peer's PeerAddress if a relay peer failed. - // It will also cancel the {@link PeerMapUpdateTask} - // maintenance task if the last relay is removed. - relayClients.remove(connection); - relayRPC.removeClient(connection); - failedRelays.add(relayAddress); - updatePeerAddress(); - - synchronized (relayListeners) { - for (RelayListener relayListener : relayListeners) { - relayListener.relayFailed(relayAddress); + synchronized (activeClients) { + if(activeClients.isEmpty() && shutdown && activity.decrementAndGet() == 0) { + shutdownFuture.done(); } } + } - }); + }); } /** @@ -369,15 +251,20 @@ public void relayFailed(PeerAddress relayAddress) { */ private void updatePeerAddress() { // add relay addresses to peer address - boolean hasRelays = !relayClients.isEmpty(); + boolean hasRelays = !activeClients.isEmpty(); - Collection socketAddresses = new ArrayList(relayClients.size()); - synchronized (relayClients) { - for (BaseRelayClient relay : relayClients) { - PeerAddress pa = relay.relayAddress(); - socketAddresses.add(new PeerSocketAddress(pa.inetAddress(), pa.tcpPort(), pa.udpPort())); + Collection socketAddresses = new ArrayList(activeClients.size()); + + //we can have more than the max relay count in our active client list. + int max = relayConfig.type().maxRelayCount(); + int i = 0; + for (PeerAddress relay : activeClients.keySet()) { + socketAddresses.add(new PeerSocketAddress(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); + if(i++ >= max) { + break; } } + // update firewalled and isRelayed flags PeerAddress newAddress = peer.peerAddress().changeFirewalledTCP(!hasRelays).changeFirewalledUDP(!hasRelays) @@ -387,7 +274,7 @@ private void updatePeerAddress() { } - @Override + /*@Override public FutureDone sendBufferRequest(String relayPeerId) { for (BaseRelayClient relayConnection : relayClients()) { String peerId = relayConnection.relayAddress().peerId().toString(); @@ -398,5 +285,5 @@ public FutureDone sendBufferRequest(String relayPeerId) { LOG.warn("No connection to relay {} found. Ignoring the message.", relayPeerId); return new FutureDone().failed("No connection to relay " + relayPeerId + " found"); - } + }*/ } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java new file mode 100644 index 000000000..e57c93e84 --- /dev/null +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -0,0 +1,176 @@ +package net.tomp2p.relay; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.tomp2p.connection.ConnectionBean; +import net.tomp2p.connection.PeerBean; +import net.tomp2p.connection.PeerConnection; +import net.tomp2p.connection.Responder; +import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.FutureDone; +import net.tomp2p.message.Message; +import net.tomp2p.message.NeighborSet; +import net.tomp2p.message.Message.Type; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerMap; +import net.tomp2p.peers.PeerStatistic; +import net.tomp2p.rpc.DispatchHandler; +import net.tomp2p.rpc.NeighborRPC; +import net.tomp2p.rpc.RPC; + +public class Forwarder extends DispatchHandler { + + private final static Logger LOG = LoggerFactory.getLogger(Forwarder.class); + private final static AtomicLong messageCounter = new AtomicLong(); + + private final PeerConnection unreachablePeerConnection; + private final RelayRPC relayRPC; + + public Forwarder(Peer peer, PeerConnection unreachablePeerConnection, RelayRPC relayRPC) { + super(peer.peerBean(), peer.connectionBean()); + this.unreachablePeerConnection = unreachablePeerConnection; + this.relayRPC = relayRPC; + } + + @Override + public void handleResponse(Message message, PeerConnection peerConnection, + boolean sign, final Responder responder) throws Exception { + // special treatment for ping and neighbor + if (message.command() == RPC.Commands.PING.getNr()) { + LOG.debug("Received message {} to handle ping for unreachable peer {}", message, unreachablePeerConnection.remotePeer()); + handlePing(message, responder); + } else if (message.command() == RPC.Commands.NEIGHBOR.getNr()) { + LOG.debug("Received message {} to handle neighbor request for unreachable peer {}", message, unreachablePeerConnection.remotePeer()); + handleNeigbhor(message, responder); + } else { + messageCounter.incrementAndGet(); + LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); + FutureDone response = relayRPC.forwardToUnreachable(message); + response.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(FutureDone future) throws Exception { + if (future.isSuccess()) { + Message answerMessage = future.object(); + LOG.debug("Returing from relay to requester: {}", answerMessage); + responder.response(answerMessage); + } else { + responder.failed(Type.DENIED, "Relaying message failed: " + future.failedReason()); + } + } + }); + } + + } + + /** + * When a ping message is received + * + * @param message + * @param responder + */ + private void handlePing(Message message, Responder responder) { + Message response = createResponseMessage(message, unreachablePeerConnection.isOpen() ? Type.OK : Type.EXCEPTION, unreachablePeerConnection.remotePeer()); + responder.response(response); + } + + /** + * When a neighbor message is received + * + * @param message + * @param responder + */ + private void handleNeigbhor(final Message message, Responder responder) { + if (message.keyList().size() < 2) { + throw new IllegalArgumentException("We need the location and domain key at least"); + } + if (!(message.type() == Type.REQUEST_1 || message.type() == Type.REQUEST_2 || message.type() == Type.REQUEST_3 || message + .type() == Type.REQUEST_4) && (message.command() == RPC.Commands.NEIGHBOR.getNr())) { + throw new IllegalArgumentException("Message content is wrong"); + } + Number160 locationKey = message.key(0); + + Collection neighbors = getNeighbors(locationKey, NeighborRPC.NEIGHBOR_SIZE); + if (neighbors == null) { + // return empty neighbor set + Message response = createResponseMessage(message, Type.NOT_FOUND, unreachablePeerConnection.remotePeer()); + response.neighborsSet(new NeighborSet(-1, Collections. emptyList())); + responder.response(response); + return; + } + + // Create response message and set neighbors + final Message responseMessage = createResponseMessage(message, Type.OK, unreachablePeerConnection.remotePeer()); + + // TODO: the relayed peer must be up-to-date here + // neighbors.add(peerConnection.remotePeer()); + + LOG.debug("found the following neighbors {}", neighbors); + + NeighborSet neighborSet = new NeighborSet(NeighborRPC.NEIGHBOR_LIMIT, neighbors); + responseMessage.neighborsSet(neighborSet); + + // we can't do fast get here, as we only send over the neighbors and not the keys stored + responder.response(responseMessage); + } + + private SortedSet getNeighbors(Number160 id, int atLeast) { + LOG.trace("Answering routing request on behalf of unreachable peer {}, neighbors of {}", unreachablePeerConnection.remotePeer(), + id); + if (peerMap == null) { + return null; + } else { + SortedSet closePeers = PeerMap.closePeers(unreachablePeerConnection.remotePeer().peerId(), id, NeighborRPC.NEIGHBOR_SIZE, + peerMap, null); + SortedSet result = new TreeSet(PeerMap.createXORAddressComparator(id)); + for (PeerStatistic p : closePeers) { + result.add(p.peerAddress()); + } + return result; + } + } + + /** + * Returns the current peer map from the mobile device + */ + public final Collection getPeerMap() { + Collection peerAddresses = new ArrayList(); + if (peerMap == null || peerMap.isEmpty()) { + return peerAddresses; + } + + Collection statistics = new ArrayList(); + for (Map map : peerMap) { + statistics.addAll(map.values()); + } + for (PeerStatistic peerStatatistic : statistics) { + peerAddresses.add(peerStatatistic.peerAddress()); + } + return peerAddresses; + } + + /** + * Update the peerMap of the unreachable peer + * + * @param peerMap the extracted peer map + * @param requestMessage the original message that contained the extracted peer map + * @param preparedResponse the response that will be sent to the unreachable peer + */ + public final void setPeerMap(List> peerMap, Message requestMessage, + Message preparedResponse) { + this.peerMap = peerMap; + peerMapUpdated(requestMessage, preparedResponse); + } + +} diff --git a/nat/src/main/java/net/tomp2p/relay/FutureRelay.java b/nat/src/main/java/net/tomp2p/relay/FutureRelay.jav similarity index 100% rename from nat/src/main/java/net/tomp2p/relay/FutureRelay.java rename to nat/src/main/java/net/tomp2p/relay/FutureRelay.jav diff --git a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java index 6f6a59dd0..c79d927ee 100644 --- a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java +++ b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java @@ -4,7 +4,9 @@ import java.util.Map; import java.util.TimerTask; +import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FutureResponse; import net.tomp2p.message.Message; @@ -12,6 +14,7 @@ import net.tomp2p.message.NeighborSet; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.relay.buffer.BufferedRelayClient; import net.tomp2p.rpc.RPC; @@ -28,7 +31,6 @@ public class PeerMapUpdateTask extends TimerTask { private static final Logger LOG = LoggerFactory.getLogger(PeerMapUpdateTask.class); - private static final long BOOTSTRAP_TIMEOUT_MS = 10000; private final RelayRPC relayRPC; private final BootstrapBuilder bootstrapBuilder; @@ -60,57 +62,15 @@ public void run() { } // bootstrap to get updated peer map and then push it to the relay peers - bootstrapBuilder.start().awaitUninterruptibly(BOOTSTRAP_TIMEOUT_MS); - - // send the peer map to the relays - List> peerMapVerified = relayRPC.peer().peerBean().peerMap().peerMapVerified(); - for (final BaseRelayClient relay : distributedRelay.relayClients()) { - sendPeerMap(relay, peerMapVerified); - } - - // try to add more relays - final FutureRelay futureRelay2 = new FutureRelay(); - distributedRelay.setupRelays(futureRelay2); - relayRPC.peer().notifyAutomaticFutures(futureRelay2); - } - - /** - * Send the peer map of an unreachable peer to a relay peer, so that the - * relay peer can reply to neighbor requests on behalf of the unreachable - * peer. - * - * @param connection - * The connection to the relay peer - * @param map - * The unreachable peer's peer map. - */ - private void sendPeerMap(final BaseRelayClient connection, List> map) { - LOG.debug("Sending current routing table to relay {}", connection.relayAddress()); - - final Message message = relayRPC - .createMessage(connection.relayAddress(), RPC.Commands.RELAY.getNr(), Type.REQUEST_3); - // TODO: neighbor size limit is 256, we might have more here - message.neighborsSet(new NeighborSet(-1, RelayUtils.flatten(map))); - - // append relay-type specific data (if necessary) - distributedRelay.relayConfig().prepareMapUpdateMessage(message); - - final FutureResponse fr = connection.sendToRelay(message); - fr.addListener(new BaseFutureAdapter() { - public void operationComplete(FutureResponse future) throws Exception { - if (future.isFailed()) { - LOG.warn("Failed to update routing table on relay peer {}. Reason: {}", connection.relayAddress(), - future.failedReason()); - connection.onMapUpdateFailed(); - } else { - LOG.trace("Updated routing table on relay {}", connection.relayAddress()); - connection.onMapUpdateSuccess(); - - // process possible buffered messages (Android only) - if(connection instanceof BufferedRelayClient) { - BufferedRelayClient bufferedConn = (BufferedRelayClient) connection; - bufferedConn.onReceiveMessageBuffer(future.responseMessage(), new FutureDone()); - } + bootstrapBuilder.start().addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureBootstrap future) + throws Exception { + // send the peer map to the relays + List> peerMapVerified = relayRPC.peer().peerBean().peerMap().peerMapVerified(); + for (final Map.Entry entry : distributedRelay.activeClients().entrySet()) { + relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + LOG.debug("send peermap to {}", entry.getKey()); } } }); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java new file mode 100644 index 000000000..6279e0089 --- /dev/null +++ b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java @@ -0,0 +1,12 @@ +package net.tomp2p.relay; + +import net.tomp2p.connection.PeerConnection; +import net.tomp2p.peers.PeerAddress; + +public interface RelayCallback { + + void onRelayAdded(PeerAddress candidate, PeerConnection object); + + void onRelayRemoved(PeerAddress candidate, PeerConnection object); + +} diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 8ba53a232..831abeaf2 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -1,8 +1,10 @@ package net.tomp2p.relay; import java.net.InetSocketAddress; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -13,15 +15,18 @@ import net.tomp2p.connection.SignatureFactory; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDone; +import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; import net.tomp2p.holep.HolePRPC; import net.tomp2p.message.Buffer; import net.tomp2p.message.Message; +import net.tomp2p.message.NeighborSet; import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerStatistic; import net.tomp2p.relay.buffer.BufferedRelayClient; import net.tomp2p.relay.buffer.BufferedRelayServer; import net.tomp2p.rpc.DispatchHandler; @@ -31,7 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RelayRPC extends DispatchHandler implements OfflineListener { +public class RelayRPC extends DispatchHandler { private static final Logger LOG = LoggerFactory.getLogger(RelayRPC.class); @@ -45,6 +50,7 @@ public class RelayRPC extends DispatchHandler implements OfflineListener { // holds the client for each server private ConcurrentHashMap clients; + /** * This variable is needed, because a relay overwrites every RPC of an @@ -86,9 +92,119 @@ public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, Map sendSetupMessage(final PeerAddress candidate, final RelayClientConfig relayConfig) { + final FutureDone futureDone = new FutureDone(); + + final Message message = createMessage(candidate, RPC.Commands.RELAY.getNr(), Type.REQUEST_1); + + // depend on the relay type whether to keep the connection open or close it after the setup. + message.keepAlive(relayConfig.type().keepConnectionOpen()); + + // encode the relay type in the message such that the relay node knows how to handle + message.intValue(relayConfig.type().ordinal()); + + // append relay-type specific data + //relayConfig.prepareSetupMessage(message); + + LOG.debug("Setting up relay connection to peer {}, message {}", candidate, message); + final FuturePeerConnection fpc = peer.createPeerConnection(candidate); + fpc.addListener(new BaseFutureAdapter() { + public void operationComplete(final FuturePeerConnection futurePeerConnection) throws Exception { + if (futurePeerConnection.isSuccess()) { + // successfully created a connection to the relay peer + final PeerConnection peerConnection = futurePeerConnection.object(); + + // send the message + FutureResponse response = RelayUtils.send(peerConnection, peer.peerBean(), peer.connectionBean(), message); + response.addListener(new BaseFutureAdapter() { + public void operationComplete(FutureResponse future) throws Exception { + if (future.isSuccess()) { + futureDone.done(peerConnection); + } else { + LOG.debug("Peer {} denied relay request", candidate); + futureDone.failed(future); + } + } + }); + } else { + LOG.debug("Unable to setup a connection to relay peer {}", candidate); + futureDone.failed(futurePeerConnection); + } + } + }); + + return futureDone; + } + + public FutureDone forwardToUnreachable(final Message message) { + // Send message via direct message through the open connection to the unreachable peer + LOG.debug("Sending {} to unreachable peer {}", message, peerConnection.remotePeer()); + final Message envelope = createMessage(peerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); + try { + message.restoreContentReferences(); + // add the message into the payload + envelope.buffer(RelayUtils.encodeMessage(message, connectionBean().channelServer().channelServerConfiguration() + .signatureFactory())); + } catch (Exception e) { + LOG.error("Cannot encode the message", e); + return new FutureDone().failed(e); + } + + // always keep the connection open + envelope.keepAlive(true); + + // this will be read RelayRPC.handlePiggyBackMessage + Collection peerSocketAddresses = new ArrayList(1); + peerSocketAddresses.add(new PeerSocketAddress(message.sender().inetAddress(), 0, 0)); + envelope.peerSocketAddresses(peerSocketAddresses); + + // holds the message that will be returned to he requester + final FutureDone futureDone = new FutureDone(); + + // Forward a message through the open peer connection to the unreachable peer. + FutureResponse fr = RelayUtils.send(peerConnection, peerBean(), connectionBean(), envelope); + fr.addListener(new BaseFutureAdapter() { + public void operationComplete(FutureResponse future) throws Exception { + if (future.isSuccess()) { + InetSocketAddress senderSocket = message.recipientSocket(); + if (senderSocket == null) { + senderSocket = unreachablePeerAddress().createSocketTCP(); + } + InetSocketAddress recipientSocket = message.senderSocket(); + if (recipientSocket == null) { + recipientSocket = message.sender().createSocketTCP(); + } + + Buffer buffer = future.responseMessage().buffer(0); + Message responseFromUnreachablePeer = RelayUtils.decodeMessage(buffer.buffer(), recipientSocket, + senderSocket, connectionBean().channelServer().channelServerConfiguration().signatureFactory()); + responseFromUnreachablePeer.restoreContentReferences(); + futureDone.done(responseFromUnreachablePeer); + } else { + futureDone.failed("Could not forward message over TCP channel"); + } + } + }); + + return futureDone; + } + + public FutureResponse sendPeerMap(final PeerAddress relayPeer, PeerConnection peerConnection, + final List> map) { + final Message message = createMessage(relayPeer, RPC.Commands.RELAY.getNr(), Type.REQUEST_3); + + message.neighborsSet(new NeighborSet(255, RelayUtils.flatten(map))); + + // append relay-type specific data (if necessary) + //relayConfig.prepareMapUpdateMessage(message); + FutureResponse response = RelayUtils.send(peerConnection, peer.peerBean(), peer.connectionBean(), message); + return response; + } /** * Receive a message at the relay server and the relay client @@ -168,60 +284,28 @@ public void removeClient(BaseRelayClient connection) { /** * Handle the setup where an unreachable peer connects to this one */ - private void handleSetup(Message message, final PeerConnection peerConnection, Responder responder) { - // The relay peer receives the setup message from the unreachable peer - if (message.intList().isEmpty()) { - throw new IllegalArgumentException("Setup message should contain an integer value specifying the type"); - } - - // get the relayType the client requests - RelayType relayType = RelayType.values()[message.intAt(0)]; - - if (serverConfigs.containsKey(relayType)) { - BaseRelayServer server = serverConfigs.get(relayType).createServer(message, peerConnection, responder, peer); - if (server != null) { - server.addOfflineListener(this); - registerRelayServer(server); - } - } else { - LOG.warn("Relay client {} requested to serve as relay with type {}. This peer does not support this type.", - message.sender(), relayType); - responder.response(createResponseMessage(message, Type.DENIED)); - } - } - - @Override - public void onUnreachableOffline(PeerAddress unreachablePeer, BaseRelayServer server) { - // clean up - servers.remove(unreachablePeer); - peerBean().removePeerStatusListener(server); - connectionBean().dispatcher().removeIoHandler(peer.peerID(), unreachablePeer.peerId()); - LOG.info("Removed {} from relay because it is offline", unreachablePeer); - } - - private void registerRelayServer(BaseRelayServer server) { + private void handleSetup(Message message, final PeerConnection unreachablePeerConnection, Responder responder) { + PeerAddress unreachablePeer = unreachablePeerConnection.remotePeer(); + Forwarder forwarder = new Forwarder(peer, unreachablePeerConnection, this); for (Commands command : RPC.Commands.values()) { if (command == RPC.Commands.RCON) { // We must register the rconRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. - dispatcher().registerIoHandler(peer.peerID(), server.unreachablePeerId(), rconRPC, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), rconRPC, command.getNr()); } else if (command == RPC.Commands.HOLEP) { // We must register the holePunchRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. - dispatcher().registerIoHandler(peer.peerID(), server.unreachablePeerId(), holePunchRPC, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), holePunchRPC, command.getNr()); } else if (command == RPC.Commands.RELAY) { // Register this class to handle all relay messages (currently used when a slow message // arrives) - dispatcher().registerIoHandler(peer.peerID(), server.unreachablePeerId(), this, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), this, command.getNr()); } else { - dispatcher().registerIoHandler(peer.peerID(), server.unreachablePeerId(), server, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), forwarder, command.getNr()); } } - - peer.peerBean().addPeerStatusListener(server); - servers.put(server.unreachablePeerId(), server); } /** diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index a339900dc..f8e474d5e 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -81,8 +81,8 @@ public Serializable execute() throws Exception { FutureDiscover fd2 = peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); - FutureNAT fn1 = pn1.startSetupPortforwarding(fd1).awaitUninterruptibly(); - FutureNAT fn2 = pn2.startSetupPortforwarding(fd2).awaitUninterruptibly(); + FutureNAT fn1 = pn1.portForwarding(fd1).awaitUninterruptibly(); + FutureNAT fn2 = pn2.portForwarding(fd2).awaitUninterruptibly(); StringBuilder sb = new StringBuilder(); if(fn1.isSuccess() && fn2.isSuccess()) { // now peer1 and peer2 know each other locally. diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 052d1e35c..31a890cb2 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -5,17 +5,21 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Random; +import java.util.concurrent.CountDownLatch; +import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.Shutdown; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.relay.BaseRelayServer; +import net.tomp2p.relay.RelayCallback; import net.tomp2p.relay.tcp.TCPRelayClientConfig; import net.tomp2p.rpc.ObjectDataReply; @@ -25,7 +29,7 @@ import org.junit.Ignore; import org.junit.Test; -@Ignore +//@Ignore public class TestNATRelay implements Serializable { private static final long serialVersionUID = 1L; @@ -64,11 +68,18 @@ public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); - PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + final CountDownLatch cl = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + }).start(); //setup relay - FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); - Assert.assertTrue(frn1.isSuccess()); + pn1.relay(); + cl.await(); peer1.objectDataReply(new ObjectDataReply() { @Override @@ -106,12 +117,19 @@ public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 1); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); - PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + final CountDownLatch cl = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + }).start(); //setup relay - FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); - System.out.println(frn1.failedReason()); - Assert.assertTrue(frn1.isSuccess()); + pn1.relay(); + cl.await(); + peer1.objectDataReply(new ObjectDataReply() { @Override @@ -176,11 +194,9 @@ public Serializable execute() throws Exception { PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); //setup relay - FutureRelayNAT frn1 = pn1.startRelay(new TCPRelayClientConfig(), fd1).awaitUninterruptibly(); - FutureRelayNAT frn2 = pn2.startRelay(new TCPRelayClientConfig(), fd2).awaitUninterruptibly(); - System.out.println(frn1.failedReason()); - Assert.assertTrue(frn1.isSuccess()); - Assert.assertTrue(frn2.isSuccess()); + Shutdown sh1 = pn1.relay(); + Shutdown sh2 = pn2.relay(); + //send message from p1 to p2 peer2.objectDataReply(new ObjectDataReply() { @Override diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index 76b702bbe..e90f9dbb6 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -43,6 +43,9 @@ --> + + + From b3142ea8ff663b7cd37afe498697bfbabff82026 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 25 Jul 2015 13:06:29 +0200 Subject: [PATCH 050/135] work log: start 11:50 - 13:05 fixed testcase with real setup for relaying. This now works in the usual case, next step is to test corner cases and make it robust. Also shutdown must now be called, which is currently under investigation --- .../java/net/tomp2p/rpc/DispatchHandler.java | 5 +- .../java/net/tomp2p/nat/PeerBuilderNAT.java | 2 +- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 2 +- .../net/tomp2p/relay/DistributedRelay.java | 3 +- .../main/java/net/tomp2p/relay/Forwarder.java | 72 ++++++++++++--- .../main/java/net/tomp2p/relay/RelayRPC.java | 87 ++++--------------- .../net/tomp2p/holep/manual/TestNATRelay.java | 22 ++--- nat/src/test/resources/nat-net.sh | 3 + 8 files changed, 102 insertions(+), 94 deletions(-) diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index 8497d7fa6..fae1044cd 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -155,7 +155,10 @@ public void forwardMessage(final Message requestMessage, PeerConnection peerConn // we can contact the peer with its address. The peer may be behind a NAT. //TODO: figure out how to include this. The only thing we currently missing are the ports - if(!requestMessage.sender().isNet4Private()) { + if(requestMessage.sender().isNet4Private() || + (requestMessage.type() == Type.REQUEST_1 && requestMessage.command() == RPC.Commands.RELAY.getNr())) { + LOG.debug("don't add the sender to the map (yet) {}", requestMessage); + } else { peerBean.notifyPeerFound(requestMessage.sender(), requestMessage.sender(), peerConnection, null); } diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index bf747deb5..20423ded4 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -207,7 +207,7 @@ public PeerNAT start() { config.start(peer); } } - final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC, relayServerConfigurations); + final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC); diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index 6a883cb3b..70635e86a 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -199,7 +199,7 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { return null; } - public Shutdown relay() { + public Shutdown startRelay() { distributedRelay.setupRelays(relayCallback); final Shutdown shutdownRelay = new Shutdown() { diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 715cedcf1..6a66eb3f7 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -215,12 +215,13 @@ public void operationComplete(final FutureDone future) @Override public void operationComplete(final FutureDone futureClose) throws Exception { + LOG.debug("lost/offline relay: {}", candidate); failedRelays.add(future.object().remotePeer()); synchronized (activeClients) { activeClients.remove(candidate, future.object()); updatePeerAddress(); } - LOG.debug("lost/offline relay: {}", candidate); + relayCallback.onRelayRemoved(candidate, future.object()); startConnectionsOpen(relayCallback); } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index e57c93e84..1d86aa085 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -1,5 +1,6 @@ package net.tomp2p.relay; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -12,19 +13,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.tomp2p.connection.ConnectionBean; -import net.tomp2p.connection.PeerBean; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Responder; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDone; +import net.tomp2p.futures.FutureResponse; +import net.tomp2p.message.Buffer; import net.tomp2p.message.Message; -import net.tomp2p.message.NeighborSet; import net.tomp2p.message.Message.Type; +import net.tomp2p.message.NeighborSet; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.NeighborRPC; @@ -36,12 +38,64 @@ public class Forwarder extends DispatchHandler { private final static AtomicLong messageCounter = new AtomicLong(); private final PeerConnection unreachablePeerConnection; - private final RelayRPC relayRPC; + private List> peerMap; - public Forwarder(Peer peer, PeerConnection unreachablePeerConnection, RelayRPC relayRPC) { + public Forwarder(Peer peer, PeerConnection unreachablePeerConnection) { super(peer.peerBean(), peer.connectionBean()); this.unreachablePeerConnection = unreachablePeerConnection; - this.relayRPC = relayRPC; + } + + public FutureDone forwardToUnreachable(final Message message) { + // Send message via direct message through the open connection to the unreachable peer + LOG.debug("Sending {} to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); + final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); + try { + message.restoreContentReferences(); + // add the message into the payload + envelope.buffer(RelayUtils.encodeMessage(message, connectionBean().channelServer().channelServerConfiguration() + .signatureFactory())); + } catch (Exception e) { + LOG.error("Cannot encode the message", e); + return new FutureDone().failed(e); + } + + // always keep the connection open + envelope.keepAlive(true); + + // this will be read RelayRPC.handlePiggyBackMessage + Collection peerSocketAddresses = new ArrayList(1); + peerSocketAddresses.add(new PeerSocketAddress(message.sender().inetAddress(), 0, 0)); + envelope.peerSocketAddresses(peerSocketAddresses); + + // holds the message that will be returned to he requester + final FutureDone futureDone = new FutureDone(); + + // Forward a message through the open peer connection to the unreachable peer. + FutureResponse fr = RelayUtils.send(unreachablePeerConnection, peerBean(), connectionBean(), envelope); + fr.addListener(new BaseFutureAdapter() { + public void operationComplete(FutureResponse future) throws Exception { + if (future.isSuccess()) { + InetSocketAddress senderSocket = message.recipientSocket(); + if (senderSocket == null) { + senderSocket = unreachablePeerConnection.remotePeer().createSocketTCP(); + } + InetSocketAddress recipientSocket = message.senderSocket(); + if (recipientSocket == null) { + recipientSocket = message.sender().createSocketTCP(); + } + + Buffer buffer = future.responseMessage().buffer(0); + Message responseFromUnreachablePeer = RelayUtils.decodeMessage(buffer.buffer(), recipientSocket, + senderSocket, connectionBean().channelServer().channelServerConfiguration().signatureFactory()); + responseFromUnreachablePeer.restoreContentReferences(); + futureDone.done(responseFromUnreachablePeer); + } else { + futureDone.failed("Could not forward message over TCP channel"); + } + } + }); + + return futureDone; } @Override @@ -57,7 +111,7 @@ public void handleResponse(Message message, PeerConnection peerConnection, } else { messageCounter.incrementAndGet(); LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); - FutureDone response = relayRPC.forwardToUnreachable(message); + FutureDone response = forwardToUnreachable(message); response.addListener(new BaseFutureAdapter>() { @Override public void operationComplete(FutureDone future) throws Exception { @@ -81,7 +135,7 @@ public void operationComplete(FutureDone future) throws Exception { * @param responder */ private void handlePing(Message message, Responder responder) { - Message response = createResponseMessage(message, unreachablePeerConnection.isOpen() ? Type.OK : Type.EXCEPTION, unreachablePeerConnection.remotePeer()); + Message response = createResponseMessage(message, unreachablePeerConnection.isOpen() ? Type.OK : Type.DENIED, unreachablePeerConnection.remotePeer()); responder.response(response); } @@ -170,7 +224,5 @@ public final Collection getPeerMap() { public final void setPeerMap(List> peerMap, Message requestMessage, Message preparedResponse) { this.peerMap = peerMap; - peerMapUpdated(requestMessage, preparedResponse); } - } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 831abeaf2..cd8c6249d 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -1,7 +1,6 @@ package net.tomp2p.relay; import java.net.InetSocketAddress; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -9,6 +8,9 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.Dispatcher; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Responder; @@ -20,8 +22,8 @@ import net.tomp2p.holep.HolePRPC; import net.tomp2p.message.Buffer; import net.tomp2p.message.Message; -import net.tomp2p.message.NeighborSet; import net.tomp2p.message.Message.Type; +import net.tomp2p.message.NeighborSet; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; @@ -33,18 +35,12 @@ import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class RelayRPC extends DispatchHandler { private static final Logger LOG = LoggerFactory.getLogger(RelayRPC.class); private final Peer peer; - // Holds a map of server configuations for multiple relay types - private final Map serverConfigs; - // holds the server for each client private final Map servers; @@ -83,10 +79,9 @@ public class RelayRPC extends DispatchHandler { * @param rconRPC the reverse connection RPC * @return */ - public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, Map serverConfigs) { + public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC) { super(peer.peerBean(), peer.connectionBean()); this.peer = peer; - this.serverConfigs = serverConfigs; this.servers = new ConcurrentHashMap(); this.clients = new ConcurrentHashMap(); this.rconRPC = rconRPC; @@ -124,6 +119,7 @@ public void operationComplete(final FuturePeerConnection futurePeerConnection) t response.addListener(new BaseFutureAdapter() { public void operationComplete(FutureResponse future) throws Exception { if (future.isSuccess()) { + LOG.debug("Peer {} accepted relay request", candidate); futureDone.done(peerConnection); } else { LOG.debug("Peer {} denied relay request", candidate); @@ -141,59 +137,6 @@ public void operationComplete(FutureResponse future) throws Exception { return futureDone; } - public FutureDone forwardToUnreachable(final Message message) { - // Send message via direct message through the open connection to the unreachable peer - LOG.debug("Sending {} to unreachable peer {}", message, peerConnection.remotePeer()); - final Message envelope = createMessage(peerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); - try { - message.restoreContentReferences(); - // add the message into the payload - envelope.buffer(RelayUtils.encodeMessage(message, connectionBean().channelServer().channelServerConfiguration() - .signatureFactory())); - } catch (Exception e) { - LOG.error("Cannot encode the message", e); - return new FutureDone().failed(e); - } - - // always keep the connection open - envelope.keepAlive(true); - - // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress(message.sender().inetAddress(), 0, 0)); - envelope.peerSocketAddresses(peerSocketAddresses); - - // holds the message that will be returned to he requester - final FutureDone futureDone = new FutureDone(); - - // Forward a message through the open peer connection to the unreachable peer. - FutureResponse fr = RelayUtils.send(peerConnection, peerBean(), connectionBean(), envelope); - fr.addListener(new BaseFutureAdapter() { - public void operationComplete(FutureResponse future) throws Exception { - if (future.isSuccess()) { - InetSocketAddress senderSocket = message.recipientSocket(); - if (senderSocket == null) { - senderSocket = unreachablePeerAddress().createSocketTCP(); - } - InetSocketAddress recipientSocket = message.senderSocket(); - if (recipientSocket == null) { - recipientSocket = message.sender().createSocketTCP(); - } - - Buffer buffer = future.responseMessage().buffer(0); - Message responseFromUnreachablePeer = RelayUtils.decodeMessage(buffer.buffer(), recipientSocket, - senderSocket, connectionBean().channelServer().channelServerConfiguration().signatureFactory()); - responseFromUnreachablePeer.restoreContentReferences(); - futureDone.done(responseFromUnreachablePeer); - } else { - futureDone.failed("Could not forward message over TCP channel"); - } - } - }); - - return futureDone; - } - public FutureResponse sendPeerMap(final PeerAddress relayPeer, PeerConnection peerConnection, final List> map) { final Message message = createMessage(relayPeer, RPC.Commands.RELAY.getNr(), Type.REQUEST_3); @@ -284,28 +227,32 @@ public void removeClient(BaseRelayClient connection) { /** * Handle the setup where an unreachable peer connects to this one */ - private void handleSetup(Message message, final PeerConnection unreachablePeerConnection, Responder responder) { - PeerAddress unreachablePeer = unreachablePeerConnection.remotePeer(); - Forwarder forwarder = new Forwarder(peer, unreachablePeerConnection, this); + private void handleSetup(Message message, final PeerConnection unreachablePeerConnectionOrig, final Responder responder) { + final Number160 unreachablePeerId = unreachablePeerConnectionOrig.remotePeer().peerId(); + final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer(unreachablePeerConnectionOrig.remotePeer().changeRelayed(true)); + //now we can add this peer to the map, as we have now set the flag + peerBean().notifyPeerFound(message.sender(), message.sender(), unreachablePeerConnectionCopy, null); for (Commands command : RPC.Commands.values()) { if (command == RPC.Commands.RCON) { // We must register the rconRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. - dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), rconRPC, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, rconRPC, command.getNr()); } else if (command == RPC.Commands.HOLEP) { // We must register the holePunchRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. - dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), holePunchRPC, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, holePunchRPC, command.getNr()); } else if (command == RPC.Commands.RELAY) { // Register this class to handle all relay messages (currently used when a slow message // arrives) - dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), this, command.getNr()); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, this, command.getNr()); } else { - dispatcher().registerIoHandler(peer.peerID(), unreachablePeer.peerId(), forwarder, command.getNr()); + final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy); + dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, forwarder, command.getNr()); } } + responder.response(createResponseMessage(message, Type.OK)); } /** diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 31a890cb2..77cd24a78 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -78,7 +78,7 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} }).start(); //setup relay - pn1.relay(); + Shutdown s = pn1.startRelay(); cl.await(); peer1.objectDataReply(new ObjectDataReply() { @@ -87,8 +87,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { return "me1"; } }); - //TODO: this is wrong here to pass the testcase find out why - Thread.sleep(1000); + PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.1.2", 5000, 1); Collection psa = new ArrayList(); psa.add(relayAddress); @@ -98,7 +97,9 @@ public Object reply(PeerAddress sender, Object request) throws Exception { System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); Assert.assertEquals("me2", fdir1.object()); - + System.err.println("DONEEEE1"); + //TODO: should also work without shutdown, figure out why not + s.shutdown(); return "tbd"; } }, new Command() { @@ -127,7 +128,7 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} }).start(); //setup relay - pn1.relay(); + Shutdown s = pn1.startRelay(); cl.await(); @@ -137,8 +138,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { return "me2"; } }); - //TODO: this is wrong here to pass the testcase find out why - Thread.sleep(1000); + PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.0.2", 5000, 0); Collection psa = new ArrayList(); psa.add(relayAddress); @@ -148,7 +148,9 @@ public Object reply(PeerAddress sender, Object request) throws Exception { System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); Assert.assertEquals("me1", fdir1.object()); - + System.err.println("DONEEEE2"); + //TODO: should also work without shutdown, figure out why not + s.shutdown(); return "tbd"; } }, new Command() { @@ -194,8 +196,8 @@ public Serializable execute() throws Exception { PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); //setup relay - Shutdown sh1 = pn1.relay(); - Shutdown sh2 = pn2.relay(); + Shutdown sh1 = pn1.startRelay(); + Shutdown sh2 = pn2.startRelay(); //send message from p1 to p2 peer2.objectDataReply(new ObjectDataReply() { diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index f78b33f98..b78db829e 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -62,6 +62,9 @@ # are to be expected. E.g., logback could hang for a minute. By adding the hostname # to /etc/hosts resolved this issue. # +# For half configured nat, use this to clean +# ps ax | grep "sudo ip" | cut -d" " -f2 | sudo xargs kill +# # Author: Thomas Bocek # Set the IP address to something in your subnet of your global namespace From 7ff3495557f04c564fb6283d30f09833873a3954 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 26 Jul 2015 17:40:37 +0200 Subject: [PATCH 051/135] work log: 16:00 - 17:40 stabilizing relay: shutdown works properly. Next test will be stress test. --- .../net/tomp2p/connection/RequestHandler.java | 4 +- .../net/tomp2p/relay/DistributedRelay.java | 126 +++++++++--------- .../net/tomp2p/holep/manual/TestNATRelay.java | 116 ++++++++++++---- nat/src/test/resources/logback.xml | 2 + nat/src/test/resources/nat-net.sh | 2 +- 5 files changed, 157 insertions(+), 93 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index e09f518e7..b2b44b074 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -291,9 +291,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo String msg = "Response message [" + responseMessage + "] sent has a different relay flag than we sent with request message [" + this.message + "]. Recipient (" + message.recipient().isRelayed() + ") / Sender (" + responseMessage.sender().isRelayed() + ")"; - exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); - responseMessage.release(); - return; + LOG.warn(msg); } //NAT reflection, change it back, as this will be stored in our peer map that may be queried from other peers diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 6a66eb3f7..4b972a602 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -4,34 +4,24 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureForkJoin; -import net.tomp2p.futures.FuturePeerConnection; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.futures.Futures; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.relay.buffer.BufferRequestListener; -import net.tomp2p.relay.buffer.BufferedRelayClient; -import net.tomp2p.rpc.RPC; import net.tomp2p.utils.ConcurrentCacheSet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * The relay manager is responsible for setting up and maintaining connections * to relay peers and contains all information about the relays. @@ -58,6 +48,8 @@ public class DistributedRelay /*implements BufferRequestListener*/ { private FutureDone shutdownFuture = new FutureDone(); private volatile boolean shutdown = false; + + final private Semaphore activeLoop = new Semaphore(1); /** * @param peer @@ -105,16 +97,13 @@ public Map activeClients() { public FutureDone shutdown() { shutdown = true; + activeLoop.release(); synchronized (activeClients) { for (Map.Entry entry: activeClients.entrySet()) { entry.getValue().close(); } } - /*synchronized (relayListeners) { - relayListeners.clear(); - }*/ - return shutdownFuture; } @@ -127,7 +116,7 @@ public FutureDone shutdown() { * @return RelayFuture containing a {@link DistributedRelay} instance */ public DistributedRelay setupRelays(final RelayCallback relayCallback) { - startConnectionsOpen(relayCallback); + startConnectionsLoop(relayCallback); return this; } @@ -167,24 +156,27 @@ private List relayCandidates() { return relayCandidates; } - final AtomicInteger activity = new AtomicInteger(0); - /** * The relay setup is called sequentially until the number of max relays is reached. If a peerconnection goes down, it will search for other relays * @param relayCallback */ - private void startConnectionsOpen(final RelayCallback relayCallback) { + + + private void startConnectionsLoop(final RelayCallback relayCallback) { + + activeLoop.acquireUninterruptibly(); - synchronized (activeClients) { - if(activity.incrementAndGet() == 1 && shutdown && activeClients.isEmpty()) { - shutdownFuture.done(); - LOG.debug("shutting down, don't restart relays"); - return; - } + if(shutdown && activeClients.isEmpty()) { + shutdownFuture.done(); + LOG.debug("shutting down, don't restart relays"); + activeLoop.release(); + return; } if(activeClients.size() >= relayConfig.type().maxRelayCount()) { LOG.debug("we have enough relays"); + //wait at most x seconds for a restart of the loop + startWaitThread(relayCallback); return; } @@ -192,6 +184,8 @@ private void startConnectionsOpen(final RelayCallback relayCallback) { final List relayCandidates = relayCandidates(); if(relayCandidates.isEmpty()) { LOG.debug("no more relays"); + //wait at most x seconds for a restart of the loop + startWaitThread(relayCallback); return; } @@ -203,13 +197,10 @@ public void operationComplete(final FutureDone future) throws Exception { if(future.isSuccess()) { - synchronized (activeClients) { - activeClients.put(candidate, future.object()); - updatePeerAddress(); - } LOG.debug("found relay: {}", candidate); + activeClients.put(candidate, future.object()); + updatePeerAddress(); relayCallback.onRelayAdded(candidate, future.object()); - startConnectionsOpen(relayCallback); future.object().closeFuture().addListener(new BaseFutureAdapter>() { @Override @@ -217,32 +208,43 @@ public void operationComplete(final FutureDone futureClose) throws Exception { LOG.debug("lost/offline relay: {}", candidate); failedRelays.add(future.object().remotePeer()); - synchronized (activeClients) { - activeClients.remove(candidate, future.object()); - updatePeerAddress(); - } + activeClients.remove(candidate, future.object()); + updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); - startConnectionsOpen(relayCallback); + + //loop again + activeLoop.release(); + //we are in a waiting thread, don't call startConnectionsLoop() } }); } else { - synchronized (activeClients) { - activeClients.remove(candidate, future.object()); - updatePeerAddress(); - } LOG.debug("bad relay: {}", candidate); + activeClients.remove(candidate, future.object()); + updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); - startConnectionsOpen(relayCallback); } - synchronized (activeClients) { - if(activeClients.isEmpty() && shutdown && activity.decrementAndGet() == 0) { - shutdownFuture.done(); - } + //loop again + activeLoop.release(); + startConnectionsLoop(relayCallback); + } + }); + } + + private void startWaitThread(final RelayCallback relayCallback) { + new Thread(new Runnable() { + @Override + public void run() { + try { + activeLoop.tryAcquire(60, TimeUnit.SECONDS); + activeLoop.release(); + startConnectionsLoop(relayCallback); + } catch (Exception e) { + e.printStackTrace(); } } - }); + }).start(); } /** @@ -251,21 +253,23 @@ public void operationComplete(final FutureDone futureClose) * relay peers. */ private void updatePeerAddress() { - // add relay addresses to peer address - boolean hasRelays = !activeClients.isEmpty(); - - Collection socketAddresses = new ArrayList(activeClients.size()); + final boolean hasRelays; + final Collection socketAddresses; + synchronized (activeClients) { + // add relay addresses to peer address + hasRelays = !activeClients.isEmpty(); + socketAddresses = new ArrayList(activeClients.size()); - //we can have more than the max relay count in our active client list. - int max = relayConfig.type().maxRelayCount(); - int i = 0; - for (PeerAddress relay : activeClients.keySet()) { - socketAddresses.add(new PeerSocketAddress(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); - if(i++ >= max) { - break; + //we can have more than the max relay count in our active client list. + int max = relayConfig.type().maxRelayCount(); + int i = 0; + for (PeerAddress relay : activeClients.keySet()) { + socketAddresses.add(new PeerSocketAddress(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); + if(i++ >= max) { + break; + } } } - // update firewalled and isRelayed flags PeerAddress newAddress = peer.peerAddress().changeFirewalledTCP(!hasRelays).changeFirewalledUDP(!hasRelays) diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 77cd24a78..ce9b30908 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -7,28 +7,24 @@ import java.util.Random; import java.util.concurrent.CountDownLatch; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; -import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.Shutdown; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.relay.BaseRelayServer; import net.tomp2p.relay.RelayCallback; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; import net.tomp2p.rpc.ObjectDataReply; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - //@Ignore public class TestNATRelay implements Serializable { @@ -78,7 +74,7 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} }).start(); //setup relay - Shutdown s = pn1.startRelay(); + pn1.startRelay(); cl.await(); peer1.objectDataReply(new ObjectDataReply() { @@ -96,16 +92,14 @@ public Object reply(PeerAddress sender, Object request) throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); - Assert.assertEquals("me2", fdir1.object()); - System.err.println("DONEEEE1"); - //TODO: should also work without shutdown, figure out why not - s.shutdown(); - return "tbd"; + System.err.println("DONE1"); + return "me2".equals(fdir1.object()) ? "TRUE" : "FALSE"; } }, new Command() { @Override public Serializable execute() throws Exception { + System.err.println("shutdown0"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -128,7 +122,7 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} }).start(); //setup relay - Shutdown s = pn1.startRelay(); + pn1.startRelay(); cl.await(); @@ -147,21 +141,21 @@ public Object reply(PeerAddress sender, Object request) throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); - Assert.assertEquals("me1", fdir1.object()); - System.err.println("DONEEEE2"); - //TODO: should also work without shutdown, figure out why not - s.shutdown(); - return "tbd"; + System.err.println("DONE2"); + return "me1".equals(fdir1.object()) ? "TRUE" : "FALSE"; } }, new Command() { @Override public Serializable execute() throws Exception { + System.err.println("shutdown1"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); unr1.waitFor(); unr2.waitFor(); + Assert.assertEquals("TRUE", unr1.getResult(0)); + Assert.assertEquals("TRUE", unr2.getResult(0)); } finally { System.out.print("LOCAL> shutdown."); @@ -172,6 +166,59 @@ public Serializable execute() throws Exception { } } + + @Test + public void testRealRelaySameNATNoRelay() throws Exception { + + RemotePeer unr1 = null; + try { + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); + + //send message from p1 to p2 + peer2.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me"; + } + }); + + put("p1", peer1); + put("p2", peer2); + + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); + PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); + //setup relay + pn1.startRelay(); + pn2.startRelay(); + + + FutureDirect fdir1 = peer1.sendDirect(peer2.peerAddress()).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("me", fdir1.object()); + //should be direct not over relay + Assert.assertEquals(0, BaseRelayServer.messageCounter()); + return "done"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + return LocalNATUtils.shutdown((Peer)get("p1"), (Peer)get("p2")); + } + }); + unr1.waitFor(); + Assert.assertEquals("done", unr1.getResult(0)); + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + @SuppressWarnings("serial") @Test public void testRealRelaySameNAT() throws Exception { @@ -191,13 +238,26 @@ public Serializable execute() throws Exception { put("p1", peer1); put("p2", peer2); - FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); - FutureDiscover fd2 = peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); - PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); - PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); + peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + + final CountDownLatch cl = new CountDownLatch(2); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + }).start(); + PeerNAT pn2 = new PeerBuilderNAT(peer2).relayCallback(new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + }).start(); //setup relay - Shutdown sh1 = pn1.startRelay(); - Shutdown sh2 = pn2.startRelay(); + pn1.startRelay(); + pn2.startRelay(); + cl.await(); //send message from p1 to p2 peer2.objectDataReply(new ObjectDataReply() { @@ -220,7 +280,7 @@ public Serializable execute() throws Exception { } }); unr1.waitFor(); - + Assert.assertEquals("done", unr1.getResult(0)); } finally { System.out.print("LOCAL> shutdown."); LocalNATUtils.shutdown(relayPeer); diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index e90f9dbb6..809ce47fd 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -46,6 +46,8 @@ + + diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index b78db829e..fe51712c1 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -63,7 +63,7 @@ # to /etc/hosts resolved this issue. # # For half configured nat, use this to clean -# ps ax | grep "sudo ip" | cut -d" " -f2 | sudo xargs kill +# pgrep -f "sudo ip" | sudo xargs kill # # Author: Thomas Bocek From 1f21098387e936073f54943e9ffab3ef438b6a28 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 26 Jul 2015 23:28:16 +0200 Subject: [PATCH 052/135] work log: 22:00 - 22:30 -cleanup distributed relay and added executor. --- .../java/net/tomp2p/nat/PeerBuilderNAT.java | 22 ++++- .../net/tomp2p/relay/DistributedRelay.java | 94 ++++++++++++------- .../java/net/tomp2p/relay/RelayCallback.java | 2 + .../tomp2p/holep/manual/LocalNATUtils.java | 18 ++-- .../net/tomp2p/holep/manual/TestNATRelay.java | 49 ++++++---- 5 files changed, 119 insertions(+), 66 deletions(-) diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index 20423ded4..a66c12355 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -3,6 +3,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +40,9 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} + + @Override + public void onFailure(Exception e) {} }; final private Peer peer; @@ -61,6 +66,8 @@ public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} private int holePNumberOfHoles = DEFAULT_NUMBER_OF_HOLEP_HOLES; private static final int DEFAULT_NUMBER_OF_HOLE_PUNCHES = 3; private int holePNumberOfPunches = DEFAULT_NUMBER_OF_HOLE_PUNCHES; + + private ExecutorService executorService; public PeerBuilderNAT(Peer peer) { this.peer = peer; @@ -168,6 +175,15 @@ public PeerBuilderNAT relayCallback(RelayCallback relayCallback) { this.relayCallback = relayCallback; return this; } + + public ExecutorService executorService() { + return executorService; + } + + public PeerBuilderNAT executorService(ExecutorService executorService) { + this.executorService = executorService; + return this; + } public PeerNAT start() { @@ -209,9 +225,11 @@ public PeerNAT start() { } final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC); + if(executorService == null) { + executorService = Executors.newSingleThreadExecutor(); + } - - DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig); + DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig, executorService); diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 4b972a602..47192078f 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -8,8 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.ExecutorService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,8 +47,8 @@ public class DistributedRelay /*implements BufferRequestListener*/ { private FutureDone shutdownFuture = new FutureDone(); private volatile boolean shutdown = false; - - final private Semaphore activeLoop = new Semaphore(1); + + final private ExecutorService executorService; /** * @param peer @@ -63,10 +62,11 @@ public class DistributedRelay /*implements BufferRequestListener*/ { * @param relayType * the kind of the relay connection */ - public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig relayConfig) { + public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig relayConfig, ExecutorService executorService) { this.peer = peer; this.relayRPC = relayRPC; this.relayConfig = relayConfig; + this.executorService = executorService; activeClients = Collections.synchronizedMap(new HashMap()); failedRelays = new ConcurrentCacheSet(relayConfig.failedRelayWaitTime()); @@ -97,13 +97,15 @@ public Map activeClients() { public FutureDone shutdown() { shutdown = true; - activeLoop.release(); synchronized (activeClients) { for (Map.Entry entry: activeClients.entrySet()) { entry.getValue().close(); } } - + executorService.shutdown(); + synchronized (peer) { + peer.notify(); + } return shutdownFuture; } @@ -116,7 +118,16 @@ public FutureDone shutdown() { * @return RelayFuture containing a {@link DistributedRelay} instance */ public DistributedRelay setupRelays(final RelayCallback relayCallback) { - startConnectionsLoop(relayCallback); + executorService.submit(new Runnable() { + @Override + public void run() { + try { + startConnectionsLoop(relayCallback); + } catch (Exception e) { + relayCallback.onFailure(e); + } + } + }); return this; } @@ -159,24 +170,38 @@ private List relayCandidates() { /** * The relay setup is called sequentially until the number of max relays is reached. If a peerconnection goes down, it will search for other relays * @param relayCallback + * @throws InterruptedException */ - private void startConnectionsLoop(final RelayCallback relayCallback) { + private void startConnectionsLoop(final RelayCallback relayCallback) throws InterruptedException { - activeLoop.acquireUninterruptibly(); - if(shutdown && activeClients.isEmpty()) { shutdownFuture.done(); LOG.debug("shutting down, don't restart relays"); - activeLoop.release(); + return; + } + + if(shutdown) { return; } if(activeClients.size() >= relayConfig.type().maxRelayCount()) { LOG.debug("we have enough relays"); //wait at most x seconds for a restart of the loop - startWaitThread(relayCallback); + executorService.submit(new Runnable() { + @Override + public void run() { + try { + synchronized (peer) { + peer.wait(60 * 1000); + } + startConnectionsLoop(relayCallback); + } catch (Exception e) { + relayCallback.onFailure(e); + } + } + }); return; } @@ -184,8 +209,19 @@ private void startConnectionsLoop(final RelayCallback relayCallback) { final List relayCandidates = relayCandidates(); if(relayCandidates.isEmpty()) { LOG.debug("no more relays"); - //wait at most x seconds for a restart of the loop - startWaitThread(relayCallback); + executorService.submit(new Runnable() { + @Override + public void run() { + try { + synchronized (peer) { + peer.wait(60 * 1000); + } + startConnectionsLoop(relayCallback); + } catch (Exception e) { + relayCallback.onFailure(e); + } + } + }); return; } @@ -213,9 +249,14 @@ public void operationComplete(final FutureDone futureClose) updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); - //loop again - activeLoop.release(); - //we are in a waiting thread, don't call startConnectionsLoop() + //notify to loop now - this may not do anything if we are shutting down + synchronized (peer) { + peer.notify(); + } + + if(shutdown && activeClients.isEmpty()) { + shutdownFuture.done(); + } } }); } else { @@ -225,28 +266,11 @@ public void operationComplete(final FutureDone futureClose) relayCallback.onRelayRemoved(candidate, future.object()); } //loop again - activeLoop.release(); startConnectionsLoop(relayCallback); } }); } - private void startWaitThread(final RelayCallback relayCallback) { - new Thread(new Runnable() { - @Override - public void run() { - try { - activeLoop.tryAcquire(60, TimeUnit.SECONDS); - activeLoop.release(); - startConnectionsLoop(relayCallback); - } catch (Exception e) { - e.printStackTrace(); - } - - } - }).start(); - } - /** * Updates the peer's PeerAddress: Adds the relay addresses to the peer * address, updates the firewalled flags, and bootstraps to announce its new diff --git a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java index 6279e0089..db86c1665 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java @@ -9,4 +9,6 @@ public interface RelayCallback { void onRelayRemoved(PeerAddress candidate, PeerConnection object); + void onFailure(Exception e); + } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 2a2e781da..32b6dca05 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -92,10 +92,13 @@ public static RemotePeer executePeer(Class klass, final int nr, final Command @Override public void run() { try { + InputStreamReader isr = new InputStreamReader(process.getInputStream()); + BufferedReader br = new BufferedReader(isr); for (int i = 0; i < cmd.length; i++) { boolean done = false; + while (!done) { - String line = read(process.getInputStream()); + String line = br.readLine(); if(line != null) { line = line.trim(); if (line.startsWith(TAG)) { @@ -114,6 +117,7 @@ public void run() { } cl.countDown(); } + process.getInputStream().close(); } catch (Throwable t) { t.printStackTrace(); } @@ -124,19 +128,12 @@ public void run() { return new RemotePeer(process, cl, cmd, results); } - public static String read(InputStream is) throws IOException { - // Read out dir output - InputStreamReader isr = new InputStreamReader(is); - BufferedReader br = new BufferedReader(isr); - return br.readLine(); - } - public static int killPeer(Process process) throws InterruptedException, IOException { - process.destroy(); process.getErrorStream().close(); process.getInputStream().close(); process.getOutputStream().close(); + process.destroy(); return process.waitFor(); } @@ -195,7 +192,7 @@ public static void handleMain(String[] args) throws ClassNotFoundException, IOEx System.out.println(TAG + LocalNATUtils.toString(e.getMessage())); } } - + System.out.flush(); } public static PeerAddress peerAddress(String ip, int port, int peerId) throws UnknownHostException { @@ -258,6 +255,7 @@ public void run() { while ((line = br.readLine()) != null) { System.out.println(type + "> " + line); } + System.out.flush(); } catch (IOException ioe) { ioe.printStackTrace(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index ce9b30908..3612d3ee5 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -62,6 +62,12 @@ public void testRealRelayDifferentNAT() throws Exception { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + peer1.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me1"; + } + }); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -71,18 +77,14 @@ public Serializable execute() throws Exception { public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {e.printStackTrace();} }).start(); //setup relay pn1.startRelay(); cl.await(); - - peer1.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return "me1"; - } - }); + Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.1.2", 5000, 1); Collection psa = new ArrayList(); @@ -92,14 +94,16 @@ public Object reply(PeerAddress sender, Object request) throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); - System.err.println("DONE1"); - return "me2".equals(fdir1.object()) ? "TRUE" : "FALSE"; + String result = fdir1.object().toString(); + System.out.println("DONE1" + result); + return "me2".equals(result) ? "TRUE" : "FALSE"; } }, new Command() { @Override public Serializable execute() throws Exception { System.err.println("shutdown0"); + Thread.sleep(500); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -110,6 +114,12 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 1); + peer1.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "me2"; + } + }); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -119,19 +129,14 @@ public Serializable execute() throws Exception { public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {e.printStackTrace();} }).start(); //setup relay pn1.startRelay(); cl.await(); - - - peer1.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return "me2"; - } - }); + Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.0.2", 5000, 0); Collection psa = new ArrayList(); @@ -141,14 +146,16 @@ public Object reply(PeerAddress sender, Object request) throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); - System.err.println("DONE2"); - return "me1".equals(fdir1.object()) ? "TRUE" : "FALSE"; + String result = fdir1.object().toString(); + System.out.println("DONE2 " + result); + return "me1".equals(result) ? "TRUE" : "FALSE"; } }, new Command() { @Override public Serializable execute() throws Exception { System.err.println("shutdown1"); + Thread.sleep(500); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -247,12 +254,16 @@ public Serializable execute() throws Exception { public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {} }).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).relayCallback(new RelayCallback() { @Override public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {} }).start(); //setup relay pn1.startRelay(); From 81cb23aaa2d505c05245c36432030527af3c3128 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 1 Aug 2015 16:48:04 +0200 Subject: [PATCH 053/135] check null value --- core/src/main/java/net/tomp2p/connection/Dispatcher.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 9ad7bfec7..1b99dd508 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -396,6 +396,9 @@ public T searchHandler(Class clazz, Number160 peerID, Number160 peerId2) readLock.lock(); try { final Map ioHandlers = search(peerID, peerId2); + if(ioHandlers == null) { + return null; + } for (DispatchHandler handler : ioHandlers.values()) { if (clazz.isInstance(handler)) { return (T) handler; From e0d1e4ec5c74d765d1c8c63ff988b34885faa7f5 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 1 Aug 2015 16:48:27 +0200 Subject: [PATCH 054/135] error reporting too verbose --- core/src/main/java/net/tomp2p/connection/RequestHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index b2b44b074..b897b22f6 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -246,7 +246,6 @@ public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cau } } - LOG.debug("Report failure: ", cause); futureResponse.failedLater(cause); ctx.close(); } From 5961721698cee4461b62e22eaddd2dce16fb68de Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 1 Aug 2015 16:48:49 +0200 Subject: [PATCH 055/135] string representation for better debugging --- core/src/main/java/net/tomp2p/message/NeighborSet.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/main/java/net/tomp2p/message/NeighborSet.java b/core/src/main/java/net/tomp2p/message/NeighborSet.java index e7029fd3b..93f59d388 100644 --- a/core/src/main/java/net/tomp2p/message/NeighborSet.java +++ b/core/src/main/java/net/tomp2p/message/NeighborSet.java @@ -63,4 +63,13 @@ public boolean equals(Object obj) { return t1 && t2; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("NeighborSet:"); + for(PeerAddress pa:neighbors) { + sb.append(pa).append(';'); + } + return sb.toString(); + } } From 464175537cb80e66b024e9ba2e5172a8af886c87 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sat, 1 Aug 2015 16:55:12 +0200 Subject: [PATCH 056/135] work log: 10:45 - 12:15 / 14:45 - 16:55 Tested and fixed relaying under different scenarios --- .../java/net/tomp2p/nat/PeerBuilderNAT.java | 17 +- .../net/tomp2p/relay/DistributedRelay.java | 62 ++- .../java/net/tomp2p/relay/RelayCallback.java | 8 +- .../main/java/net/tomp2p/relay/RelayRPC.java | 46 +- .../tomp2p/holep/manual/LocalNATUtils.java | 25 +- .../holep/manual/RemotePeerCallback.java | 9 + .../net/tomp2p/holep/manual/TestNATLocal.java | 2 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 495 +++++++++++++++--- .../holep/manual/TestNATTypeDetection.java | 2 +- 9 files changed, 564 insertions(+), 102 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/RemotePeerCallback.java diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index a66c12355..203abcdfb 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -2,7 +2,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -14,12 +13,12 @@ import net.tomp2p.futures.FutureDone; import net.tomp2p.holep.HolePInitiatorImpl; import net.tomp2p.holep.HolePRPC; -import net.tomp2p.message.Message; +import net.tomp2p.holep.HolePScheduler; +import net.tomp2p.holep.strategy.HolePStrategy; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.Shutdown; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayClient; import net.tomp2p.relay.DistributedRelay; import net.tomp2p.relay.RconRPC; import net.tomp2p.relay.RelayCallback; @@ -43,6 +42,12 @@ public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} @Override public void onFailure(Exception e) {} + + @Override + public void onFullRelays() {} + + @Override + public void onNoMoreRelays() {} }; final private Peer peer; @@ -229,11 +234,7 @@ public PeerNAT start() { executorService = Executors.newSingleThreadExecutor(); } - DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig, executorService); - - - - + DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig, executorService, bootstrapBuilder); peer.addShutdownListener(new Shutdown() { @Override diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 47192078f..8ed89a508 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -14,11 +14,18 @@ import org.slf4j.LoggerFactory; import net.tomp2p.connection.PeerConnection; +import net.tomp2p.connection.PeerException; +import net.tomp2p.connection.PeerException.AbortCause; import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDone; import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.builder.BootstrapBuilder; +import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerMapChangeListener; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerStatistic; import net.tomp2p.utils.ConcurrentCacheSet; /** @@ -30,7 +37,7 @@ * @author Nico Rutishauser * */ -public class DistributedRelay /*implements BufferRequestListener*/ { +public class DistributedRelay implements PeerMapChangeListener { private final static Logger LOG = LoggerFactory.getLogger(DistributedRelay.class); @@ -47,8 +54,11 @@ public class DistributedRelay /*implements BufferRequestListener*/ { private FutureDone shutdownFuture = new FutureDone(); private volatile boolean shutdown = false; + private boolean allRelays = false; final private ExecutorService executorService; + final private BootstrapBuilder bootstrapBuilder; + /** * @param peer @@ -57,20 +67,22 @@ public class DistributedRelay /*implements BufferRequestListener*/ { * the relay RPC * @param maxFail * @param relayConfig + * @param bootstrapBuilder * @param maxRelays * maximum number of relay peers to set up * @param relayType * the kind of the relay connection */ - public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig relayConfig, ExecutorService executorService) { + public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig relayConfig, ExecutorService executorService, BootstrapBuilder bootstrapBuilder) { this.peer = peer; this.relayRPC = relayRPC; this.relayConfig = relayConfig; this.executorService = executorService; + this.bootstrapBuilder = bootstrapBuilder; activeClients = Collections.synchronizedMap(new HashMap()); failedRelays = new ConcurrentCacheSet(relayConfig.failedRelayWaitTime()); - //relayListeners = Collections.synchronizedList(new ArrayList(1)); + peer.peerBean().peerMap().addPeerMapChangeListener(this); } public RelayClientConfig relayConfig() { @@ -97,6 +109,7 @@ public Map activeClients() { public FutureDone shutdown() { shutdown = true; + peer.peerBean().peerMap().removePeerMapChangeListener(this); synchronized (activeClients) { for (Map.Entry entry: activeClients.entrySet()) { entry.getValue().close(); @@ -188,6 +201,9 @@ private void startConnectionsLoop(final RelayCallback relayCallback) throws Inte if(activeClients.size() >= relayConfig.type().maxRelayCount()) { LOG.debug("we have enough relays"); + allRelays = true; + relayCallback.onFullRelays(); + updatePeerMap(); //wait at most x seconds for a restart of the loop executorService.submit(new Runnable() { @Override @@ -209,6 +225,8 @@ public void run() { final List relayCandidates = relayCandidates(); if(relayCandidates.isEmpty()) { LOG.debug("no more relays"); + relayCallback.onNoMoreRelays(); + updatePeerMap(); executorService.submit(new Runnable() { @Override public void run() { @@ -242,7 +260,10 @@ public void operationComplete(final FutureDone future) @Override public void operationComplete(final FutureDone futureClose) throws Exception { + LOG.debug("lost/offline relay: {}", candidate); + //we need to notify our map, since we know this peer is offline, TODO: make this generic for all PeerConnections + peer.peerBean().peerMap().peerFailed(candidate, new PeerException(AbortCause.SHUTDOWN, "remote open peer connection was closed")); failedRelays.add(future.object().remotePeer()); activeClients.remove(candidate, future.object()); @@ -251,6 +272,7 @@ public void operationComplete(final FutureDone futureClose) //notify to loop now - this may not do anything if we are shutting down synchronized (peer) { + allRelays = false; peer.notify(); } @@ -302,7 +324,41 @@ private void updatePeerAddress() { LOG.debug("Updated peer address {}, isrelay = {}", newAddress, hasRelays); } + @Override + public void peerInserted(PeerAddress peerAddress, boolean verified) { + LOG.debug("new peer added, go again "+peerAddress+ " / "+verified); + synchronized (peer) { + if(!allRelays) { + peer.notify(); + } + } + } + + @Override + public void peerRemoved(PeerAddress peerAddress, + PeerStatistic storedPeerAddress) {} + + @Override + public void peerUpdated(PeerAddress peerAddress, + PeerStatistic storedPeerAddress) {} + + private void updatePeerMap() { + // bootstrap to get updated peer map and then push it to the relay peers + bootstrapBuilder.start().addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureBootstrap future) + throws Exception { + // send the peer map to the relays + List> peerMapVerified = relayRPC.peer().peerBean().peerMap().peerMapVerified(); + for (final Map.Entry entry : activeClients().entrySet()) { + relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + LOG.debug("send peermap to {}", entry.getKey()); + } + } + }); + } + /*@Override public FutureDone sendBufferRequest(String relayPeerId) { for (BaseRelayClient relayConnection : relayClients()) { diff --git a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java index db86c1665..944317d22 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java @@ -5,10 +5,14 @@ public interface RelayCallback { - void onRelayAdded(PeerAddress candidate, PeerConnection object); + void onRelayAdded(PeerAddress relay, PeerConnection object); - void onRelayRemoved(PeerAddress candidate, PeerConnection object); + void onRelayRemoved(PeerAddress relay, PeerConnection object); void onFailure(Exception e); + void onFullRelays(); + + void onNoMoreRelays(); + } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index cd8c6249d..8bf2a5634 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -42,10 +42,10 @@ public class RelayRPC extends DispatchHandler { private final Peer peer; // holds the server for each client - private final Map servers; + //private final Map servers; // holds the client for each server - private ConcurrentHashMap clients; + //private ConcurrentHashMap clients; /** @@ -82,8 +82,8 @@ public class RelayRPC extends DispatchHandler { public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC) { super(peer.peerBean(), peer.connectionBean()); this.peer = peer; - this.servers = new ConcurrentHashMap(); - this.clients = new ConcurrentHashMap(); + //this.servers = new ConcurrentHashMap(); + //this.clients = new ConcurrentHashMap(); this.rconRPC = rconRPC; this.holePunchRPC = holePRPC; @@ -141,10 +141,12 @@ public FutureResponse sendPeerMap(final PeerAddress relayPeer, PeerConnection pe final List> map) { final Message message = createMessage(relayPeer, RPC.Commands.RELAY.getNr(), Type.REQUEST_3); - message.neighborsSet(new NeighborSet(255, RelayUtils.flatten(map))); - + NeighborSet ns = new NeighborSet(255, RelayUtils.flatten(map)); + message.neighborsSet(ns); + LOG.debug("send neigbors " + ns); // append relay-type specific data (if necessary) //relayConfig.prepareMapUpdateMessage(message); + message.keepAlive(true); FutureResponse response = RelayUtils.send(peerConnection, peer.peerBean(), peer.connectionBean(), message); return response; } @@ -168,10 +170,10 @@ public void handleResponse(final Message message, PeerConnection peerConnection, } else if (message.type() == Type.REQUEST_4 && message.command() == RPC.Commands.RELAY.getNr()) { // An unreachable peer requests the buffer at the relay peer // or a buffer is transmitted to the unreachable peer directly - handleBuffer(message, responder); + //handleBuffer(message, responder); } else if (message.type() == Type.REQUEST_5 && message.command() == RPC.Commands.RELAY.getNr()) { // A late response - handleLateResponse(message, peerConnection, sign, responder); + //handleLateResponse(message, peerConnection, sign, responder); } else { throw new IllegalArgumentException("Message content is wrong"); } @@ -202,27 +204,27 @@ private Dispatcher dispatcher() { /** * @return all unreachable peers currently connected to this relay node */ - public Set unreachablePeers() { + /*public Set unreachablePeers() { Set unreachablePeers = new HashSet(servers.size()); for (BaseRelayServer forwarder : servers.values()) { unreachablePeers.add(forwarder.unreachablePeerAddress()); } return unreachablePeers; - } + }*/ /** * Add a client to the list */ - public void addClient(BaseRelayClient connection) { + /*public void addClient(BaseRelayClient connection) { clients.put(connection.relayAddress().peerId(), connection); - } + }*/ /** * Remove a client from the list */ - public void removeClient(BaseRelayClient connection) { + /*public void removeClient(BaseRelayClient connection) { clients.remove(connection.relayAddress().peerId()); - } + }*/ /** * Handle the setup where an unreachable peer connects to this one @@ -329,11 +331,13 @@ public void responseFireAndForget() { */ private void handleMap(Message message, Responder responder) { LOG.debug("Handle foreign map update {}", message); - BaseRelayServer server = servers.get(message.sender().peerId()); - if (server != null) { + + final Forwarder forwarder = dispatcher().searchHandler(Forwarder.class, peer.peerAddress().peerId(), message.sender().peerId()); + + if (forwarder != null) { Collection map = message.neighborsSet(0).neighbors(); Message response = createResponseMessage(message, Type.OK); - server.setPeerMap(RelayUtils.unflatten(map, message.sender()), message, response); + forwarder.setPeerMap(RelayUtils.unflatten(map, message.sender()), message, response); responder.response(response); } else { LOG.error("No forwarder for peer {} found. Need to setup relay first"); @@ -354,7 +358,7 @@ private void handleMap(Message message, Responder responder) { * @param message * @param responder */ - private void handleBuffer(final Message message, final Responder responder) { + /*private void handleBuffer(final Message message, final Responder responder) { BaseRelayServer server = servers.get(message.sender().peerId()); BaseRelayClient client = clients.get(message.sender().peerId()); if (server != null && server instanceof BufferedRelayServer) { @@ -385,7 +389,7 @@ public void operationComplete(FutureDone future) throws Exception { } else { responder.failed(Type.EXCEPTION, "This message type is intended for buffering forwarders only"); } - } + }*/ /** * There are two possibilites for this case: @@ -399,7 +403,7 @@ public void operationComplete(FutureDone future) throws Exception { * @param peerConnection * @param sign */ - private void handleLateResponse(Message message, PeerConnection peerConnection, boolean sign, Responder responder) { + /*private void handleLateResponse(Message message, PeerConnection peerConnection, boolean sign, Responder responder) { if (!message.sender().isSlow() || message.bufferList().isEmpty()) { throw new IllegalArgumentException( "Late response does not come from slow peer or does not contain the buffered message"); @@ -445,5 +449,5 @@ private void handleLateResponse(Message message, PeerConnection peerConnection, forwarder.forwardToUnreachable(message); } } - } + }*/ } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 32b6dca05..3c57f9b40 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -25,6 +25,13 @@ public class LocalNATUtils { private static final String TAG = "##BASE64##:"; + private static final RemotePeerCallback DEFAULT_CALLBACK = new RemotePeerCallback() { + @Override + public void onNull(int i) {} + @Override + public void onFinished(int i) {} + }; + /** * If you have a terrible lag in InetAddress.getLocalHost(), make sure the * hostname resolves in the other network domain. @@ -59,8 +66,18 @@ public static RemotePeer executePeer(int nr, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { return executePeer(LocalNATUtils.class, nr, cmd); } + + public static RemotePeer executePeer(int nr, final RemotePeerCallback remoteCallback, final Command... cmd) + throws IOException, InterruptedException, ClassNotFoundException { + return executePeer(LocalNATUtils.class, nr, remoteCallback, cmd); + } + + public static RemotePeer executePeer(Class klass, int nr, final Command... cmd) + throws IOException, InterruptedException, ClassNotFoundException { + return executePeer(LocalNATUtils.class, nr, DEFAULT_CALLBACK, cmd); + } - public static RemotePeer executePeer(Class klass, final int nr, final Command... cmd) + public static RemotePeer executePeer(Class klass, final int nr, final RemotePeerCallback remoteCallback, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator @@ -112,10 +129,12 @@ public void run() { } else { System.out.println("OUT["+nr+"]>null"); cl.countDown(); + remoteCallback.onNull(i); break; } } cl.countDown(); + remoteCallback.onFinished(i); } process.getInputStream().close(); } catch (Throwable t) { @@ -140,12 +159,12 @@ public static int killPeer(Process process) throws InterruptedException, /** * As set in: tomp2p/nat/src/test/resources/nat-net.sh */ - public static Peer createRealNode(Number160 relayPeerId, String iface) + public static Peer createRealNode(Number160 relayPeerId, String iface, int port) throws Exception { // relay Bindings b2 = new Bindings(); b2.addInterface(iface); - return new PeerBuilder(relayPeerId).ports(5002).bindings(b2).start(); + return new PeerBuilder(relayPeerId).ports(port).bindings(b2).start(); } /** diff --git a/nat/src/test/java/net/tomp2p/holep/manual/RemotePeerCallback.java b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeerCallback.java new file mode 100644 index 000000000..9fb99e8dc --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeerCallback.java @@ -0,0 +1,9 @@ +package net.tomp2p.holep.manual; + +public interface RemotePeerCallback { + + void onNull(int i); + + void onFinished(int i); + +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index f8e474d5e..a508b38cc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -64,7 +64,7 @@ public void testLocalSend() throws Exception { Peer relayPeer = null; RemotePeer unr1 = null; try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 3612d3ee5..2d13efd71 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -2,10 +2,13 @@ import java.io.IOException; import java.io.Serializable; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Random; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import org.junit.After; import org.junit.Assert; @@ -22,6 +25,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.relay.BaseRelayServer; +import net.tomp2p.relay.Forwarder; import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; @@ -30,7 +34,11 @@ public class TestNATRelay implements Serializable { private static final long serialVersionUID = 1L; final static private Random RND = new Random(42); - static private Number160 relayPeerId = new Number160(RND); + static private Number160 relayPeerId1 = new Number160(RND); + static private Number160 relayPeerId2 = new Number160(RND); + static private Number160 relayPeerId3 = new Number160(RND); + static private Number160 relayPeerId4 = new Number160(RND); + static private Number160 relayPeerId5 = new Number160(RND); //### CHANGE THIS TO YOUR INTERFACE### final static private String INF = "eth1"; @@ -46,6 +54,408 @@ public void after() throws IOException, InterruptedException { LocalNATUtils.executeNatSetup("stop", "1"); } + /** + * Test if a relay goes offline to contact a new relay. The following cases are tested: + * + * 1 relay, 1 goes offline, 1 new relay joins, find new relay, add this relay. This test is time sensitive. + * + * @throws Exception + */ + @Test + public void testRelayFailover1() throws Exception { + Peer relayPeer1 = null; + Peer relayPeer2 = null; + RemotePeer unr1 = null; + try { + relayPeer1 = createRelay(relayPeerId1, 5002); + relayPeer2 = createRelay(relayPeerId2, 5003); + final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + + final Peer relayPeer1Copy = relayPeer1; + + unr1 = LocalNATUtils.executePeer(0, new RemotePeerCallback() { + + @Override + public void onNull(int i) {} + + @Override + public void onFinished(int i) { + if(i==0) { + //shutdown relay1 + System.out.println("go offline!"); + relayPeer1Copy.shutdown().awaitUninterruptibly(); + } + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + + final CountDownLatch cl1 = new CountDownLatch(1); + final CountDownLatch cl2 = new CountDownLatch(1); + put("cl2", cl2); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback2(cl1, cl2)).start(); + //setup relay + pn1.startRelay(); + cl1.await(); + //make sure no further relays are searched in the next 5 sec. Check manually! + + return "shutdown relay1"; + } + + + + }, new Command() { + + @Override + public Serializable execute() throws Exception { + final Peer peer1 = (Peer) get("p1"); + //discover the 2nd relay + peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + System.out.println("now we know peer realy2 "); + final CountDownLatch cl2 = (CountDownLatch) get("cl2"); + cl2.await(); + return "done"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown0"); + Thread.sleep(500); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + Assert.assertEquals("done", unr1.getResult(1)); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer1, relayPeer2); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + + /** + * Test if a relay goes offline to contact a new relay. The following cases are tested: + * + * 2 relays, 1 goes offline, switch to the other one + * + * @throws Exception + */ + @Test + public void testRelayFailover2() throws Exception { + Peer relayPeer1 = null; + Peer relayPeer2 = null; + RemotePeer unr1 = null; + try { + relayPeer1 = createRelay(relayPeerId1, 5002); + final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + relayPeer2 = createRelay(relayPeerId2, 5003); + final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + + final Peer relayPeer1Copy = relayPeer1; + final Peer relayPeer2Copy = relayPeer2; + final AtomicBoolean test = new AtomicBoolean(false); + unr1 = LocalNATUtils.executePeer(0, new RemotePeerCallback() { + + @Override + public void onNull(int i) {} + + @Override + public void onFinished(int i) { + if(i==0) { + //shutdown relay1 + System.out.println("go offline!"); + relayPeer1Copy.shutdown().awaitUninterruptibly(); + } else if(i==1) { + Forwarder fw = relayPeer2Copy.connectionBean().dispatcher().searchHandler(Forwarder.class, relayPeer2Copy.peerID() , Number160.createHash(0)); + System.out.println("SIIIZE: " + fw.getPeerMap().size()); + test.set(fw.getPeerMap().size() == 1); + } + + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + FutureDiscover fd2 = peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + Assert.assertFalse(fd2.isDiscoveredTCP()); + + final CountDownLatch cl = new CountDownLatch(2); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl)).start(); + //setup relay + pn1.startRelay(); + cl.await(); + //make sure no further relays are searched in the next 5 sec. Check manually! + + return "shutdown relay1"; + } + + + + }, new Command() { + + @Override + public Serializable execute() throws Exception { + System.out.println("wait 5 sec"); + Thread.sleep(5000); + System.out.println("done wait 5 sec"); + //now relay1 is shutdown, check if we updated our data + return "check relay2"; + } + }, new Command() { + + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown0"); + Thread.sleep(500); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + Assert.assertTrue(test.get()); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer1, relayPeer2); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + + /** + * Test if we wait if we have all relay peers + * @throws Exception + */ + @Test + public void testFullRelay() throws Exception { + Peer relayPeer1 = null; + Peer relayPeer2 = null; + Peer relayPeer3 = null; + Peer relayPeer4 = null; + Peer relayPeer5 = null; + RemotePeer unr1 = null; + try { + relayPeer1 = createRelay(relayPeerId1, 5002); + final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + relayPeer2 = createRelay(relayPeerId2, 5003); + final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + relayPeer3 = createRelay(relayPeerId3, 5004); + final PeerSocketAddress relayAddress3 = relayPeer3.peerAddress().peerSocketAddress(); + relayPeer4 = createRelay(relayPeerId4, 5005); + final PeerSocketAddress relayAddress4 = relayPeer4.peerAddress().peerSocketAddress(); + relayPeer5 = createRelay(relayPeerId5, 5006); + final PeerSocketAddress relayAddress5 = relayPeer5.peerAddress().peerSocketAddress(); + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + FutureDiscover fd2 = peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + FutureDiscover fd3 = peer1.discover().peerSocketAddress(relayAddress3).start().awaitUninterruptibly(); + FutureDiscover fd4 = peer1.discover().peerSocketAddress(relayAddress4).start().awaitUninterruptibly(); + FutureDiscover fd5 = peer1.discover().peerSocketAddress(relayAddress5).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + Assert.assertFalse(fd2.isDiscoveredTCP()); + Assert.assertFalse(fd3.isDiscoveredTCP()); + Assert.assertFalse(fd4.isDiscoveredTCP()); + Assert.assertFalse(fd5.isDiscoveredTCP()); + + + final CountDownLatch cl = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallbackFull(cl)).start(); + //setup relay + pn1.startRelay(); + cl.await(); + //make sure no further relays are searched in the next 5 sec. Check manually! + Thread.sleep(5000); + return "done"; + } + + + + }, new Command() { + + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown0"); + Thread.sleep(500); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + Assert.assertEquals("done", unr1.getResult(0)); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer1, relayPeer2, relayPeer3, relayPeer4, relayPeer5); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + + /** + * Test if a new relay that was discovered is added + * @throws Exception + */ + @Test + public void testLateRelay() throws Exception { + Peer relayPeer1 = null; + Peer relayPeer2 = null; + RemotePeer unr1 = null; + try { + relayPeer1 = createRelay(relayPeerId1, 5002); + final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + relayPeer2 = createRelay(relayPeerId2, 5003); + final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + + unr1 = LocalNATUtils.executePeer(0, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + put("p1", peer1); + //get to know both relays + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + + + final CountDownLatch cl = new CountDownLatch(2); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl)).start(); + //setup relay + + pn1.startRelay(); + Thread.sleep(500); + FutureDiscover fd2 = peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + Assert.assertFalse(fd2.isDiscoveredTCP()); + + cl.await(); + + return "done"; + } + + + + }, new Command() { + + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown0"); + Thread.sleep(500); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + Assert.assertEquals("done", unr1.getResult(0)); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer1, relayPeer2); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + + private Peer createRelay(Number160 relayPeerId, int port) throws Exception { + Peer relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, port); + new PeerBuilderNAT(relayPeer).start(); + return relayPeer; + } + + private PeerNAT createRelay2(Number160 relayPeerId, int port) throws Exception { + Peer relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, port); + return new PeerBuilderNAT(relayPeer).start(); + } + + private Peer createNattedPeer(final String ip, final int port, final int nr, final String retVal) + throws UnknownHostException, IOException { + Peer peer = LocalNATUtils.init(ip, port, nr); + peer.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return retVal; + } + }); + return peer; + } + + private RelayCallback countDownRelayCallback( + final CountDownLatch cl) { + return new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {e.printStackTrace();} + @Override + public void onFullRelays() {} + @Override + public void onNoMoreRelays() {} + }; + } + private RelayCallback countDownRelayCallback2( + final CountDownLatch cl1, final CountDownLatch cl2) { + return new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) { + if(cl1.getCount() > 0 ) { + cl1.countDown(); + } else { + cl2.countDown(); + } + } + @Override + public void onFailure(Exception e) {e.printStackTrace();} + @Override + public void onFullRelays() {} + @Override + public void onNoMoreRelays() {} + }; + } + + private RelayCallback countDownRelayCallbackFull( + final CountDownLatch cl) { + return new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} + @Override + public void onFailure(Exception e) {e.printStackTrace();} + @Override + public void onFullRelays() {cl.countDown();} + @Override + public void onNoMoreRelays() {} + }; + } + + @SuppressWarnings("serial") @Test public void testRealRelayDifferentNAT() throws Exception { @@ -53,33 +463,19 @@ public void testRealRelayDifferentNAT() throws Exception { RemotePeer unr1 = null; RemotePeer unr2 = null; try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); - PeerNAT rn1 = new PeerBuilderNAT(relayPeer).start(); + relayPeer = createRelay(relayPeerId1, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); unr1 = LocalNATUtils.executePeer(0, new Command() { @Override public Serializable execute() throws Exception { - Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); - peer1.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return "me1"; - } - }); + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); final CountDownLatch cl = new CountDownLatch(1); - PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { - @Override - public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} - @Override - public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} - @Override - public void onFailure(Exception e) {e.printStackTrace();} - }).start(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl)).start(); //setup relay pn1.startRelay(); @@ -98,6 +494,8 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} System.out.println("DONE1" + result); return "me2".equals(result) ? "TRUE" : "FALSE"; } + + }, new Command() { @Override @@ -113,25 +511,12 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 1); - peer1.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return "me2"; - } - }); + Peer peer1 = createNattedPeer("10.0.1.2", 5000, 1, "me2"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); final CountDownLatch cl = new CountDownLatch(1); - PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { - @Override - public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} - @Override - public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} - @Override - public void onFailure(Exception e) {e.printStackTrace();} - }).start(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl)).start(); //setup relay pn1.startRelay(); @@ -183,20 +568,18 @@ public void testRealRelaySameNATNoRelay() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); - Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); - - //send message from p1 to p2 - peer2.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return "me"; - } - }); + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "n/a"); put("p1", peer1); + + Peer peer2 = createNattedPeer("10.0.0.3", 5001, 1, "me"); put("p2", peer2); + + + + + PeerNAT pn1 = new PeerBuilderNAT(peer1).start(); PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); //setup relay @@ -232,39 +615,25 @@ public void testRealRelaySameNAT() throws Exception { Peer relayPeer = null; RemotePeer unr1 = null; try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); - PeerNAT rn1 = new PeerBuilderNAT(relayPeer).start(); + relayPeer = createRelay(relayPeerId1, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); unr1 = LocalNATUtils.executePeer(0, new Command() { @Override public Serializable execute() throws Exception { - Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); - Peer peer2 = LocalNATUtils.init("10.0.0.3", 5001, 1); + Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "n/a"); put("p1", peer1); + + Peer peer2 = createNattedPeer("10.0.0.3", 5001, 1, "me"); put("p2", peer2); peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); peer2.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); final CountDownLatch cl = new CountDownLatch(2); - PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(new RelayCallback() { - @Override - public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} - @Override - public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} - @Override - public void onFailure(Exception e) {} - }).start(); - PeerNAT pn2 = new PeerBuilderNAT(peer2).relayCallback(new RelayCallback() { - @Override - public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} - @Override - public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} - @Override - public void onFailure(Exception e) {} - }).start(); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl)).start(); + PeerNAT pn2 = new PeerBuilderNAT(peer2).relayCallback(countDownRelayCallback(cl)).start(); //setup relay pn1.startRelay(); pn2.startRelay(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index cd8ecf9be..9100087b4 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -73,7 +73,7 @@ public void testDetection() throws Exception { RemotePeer unr1 = null; RemotePeer unr2 = null; try { - relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF); + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); final String address = relayAddress.getHostAddress(); unr1 = LocalNATUtils.executePeer(0, From 4913937ff30bece9a49f8d42a0042bb3226a2033 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 2 Aug 2015 17:25:10 +0200 Subject: [PATCH 057/135] work log: 10:40 - 12:00 / 16:20 - 17:25 cleaned up code and removed unused code. Android package is now deleted as the default Android handling won't be GCM, but the open TCP connection. Lots of configuration code could be removed. The project now compiles again. However, Android handling is not tested. Next step: test and polish examples, make stress test, add more corner-cases testcases --- all/pom.xml | 5 - android/.gitignore | 11 - android/pom.xml | 86 -- .../relay/android/AndroidRelayClient.java | 119 --- .../android/AndroidRelayClientConfig.java | 112 --- .../relay/android/AndroidRelayServer.java | 85 -- .../android/AndroidRelayServerConfig.java | 111 --- .../tomp2p/relay/android/gcm/FutureGCM.java | 40 - .../relay/android/gcm/GCMSenderRPC.java | 140 --- .../tomp2p/relay/android/gcm/IGCMSender.java | 11 - .../relay/android/gcm/RemoteGCMSender.java | 87 -- .../android/AssertingSlowPeerFilter.java | 41 - .../android/MockedAndroidRelayClient.java | 36 - .../MockedAndroidRelayClientConfig.java | 42 - .../MockedAndroidRelayServerConfig.java | 25 - .../tomp2p/relay/android/MockedGCMSender.java | 42 - .../relay/android/TestAndroidRelay.java | 221 ----- .../net/tomp2p/relay/android/TestRelay.java | 878 ------------------ .../net/tomp2p/relay/android/UtilsNAT.java | 254 ----- android/src/test/resources/logback.xml | 24 - .../net/tomp2p/examples/ExampleHoleP.java | 11 +- .../java/net/tomp2p/examples/ExampleNAT.java | 64 +- .../java/net/tomp2p/examples/TomP2PTests.java | 100 +- .../java/net/tomp2p/nat/FutureRelayNAT.java | 60 -- .../java/net/tomp2p/nat/PeerBuilderNAT.java | 76 +- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 21 +- .../net/tomp2p/relay/DistributedRelay.java | 47 +- .../main/java/net/tomp2p/relay/Forwarder.java | 62 +- .../net/tomp2p/relay/PeerMapUpdateTask.java | 13 +- .../java/net/tomp2p/relay/RelayCallback.java | 6 +- .../net/tomp2p/relay/RelayClientConfig.java | 167 ---- .../main/java/net/tomp2p/relay/RelayRPC.java | 189 ++-- .../net/tomp2p/relay/RelayServerConfig.java | 34 - .../java/net/tomp2p/relay/RelayUtils.java | 12 +- .../relay/buffer/BufferRequestListener.java | 13 - .../relay/buffer/BufferedMessageHandler.java | 133 --- .../relay/buffer/BufferedRelayClient.java | 35 - .../relay/buffer/BufferedRelayServer.java | 134 --- .../tomp2p/relay/buffer/MessageBuffer.java | 188 ---- .../buffer/MessageBufferConfiguration.java | 118 --- .../relay/buffer/MessageBufferListener.java | 23 - .../net/tomp2p/relay/tcp/TCPRelayClient.java | 65 -- .../relay/tcp/TCPRelayClientConfig.java | 34 - .../net/tomp2p/relay/tcp/TCPRelayServer.java | 129 --- .../relay/tcp/TCPRelayServerConfig.java | 37 - .../tcp/buffered/BufferedTCPRelayClient.java | 55 -- .../BufferedTCPRelayClientConfig.java | 31 - .../tcp/buffered/BufferedTCPRelayServer.java | 61 -- .../BufferedTCPRelayServerConfig.java | 43 - .../net/tomp2p/holep/AbstractTestHoleP.java | 118 --- .../net/tomp2p/holep/HolePStressTest.java | 55 -- .../IntegrationTestBootstrapBuilder.java | 59 -- .../holep/IntegrationTestHolePuncher.java | 21 - .../net/tomp2p/holep/manual/TestNATRelay.java | 24 +- .../test/java/net/tomp2p/relay/TestRcon.java | 17 +- .../test/java/net/tomp2p/relay/TestRelay.java | 855 ----------------- .../tomp2p/relay/TestRelayReplication.java | 114 --- .../relay/buffer/TestMessageBuffer.java | 205 ---- pom.xml | 1 - 59 files changed, 328 insertions(+), 5472 deletions(-) delete mode 100644 android/.gitignore delete mode 100644 android/pom.xml delete mode 100644 android/src/main/java/net/tomp2p/relay/android/AndroidRelayClient.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/AndroidRelayClientConfig.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/AndroidRelayServer.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/AndroidRelayServerConfig.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/gcm/FutureGCM.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/gcm/GCMSenderRPC.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/gcm/IGCMSender.java delete mode 100644 android/src/main/java/net/tomp2p/relay/android/gcm/RemoteGCMSender.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/AssertingSlowPeerFilter.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClient.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClientConfig.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayServerConfig.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/MockedGCMSender.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/TestAndroidRelay.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/TestRelay.java delete mode 100644 android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java delete mode 100644 android/src/test/resources/logback.xml delete mode 100644 nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/RelayClientConfig.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/RelayServerConfig.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/BufferRequestListener.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/BufferedMessageHandler.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayClient.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayServer.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/MessageBuffer.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferConfiguration.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferListener.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClient.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClientConfig.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServer.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServerConfig.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClient.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClientConfig.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServer.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServerConfig.java delete mode 100644 nat/src/test/java/net/tomp2p/holep/AbstractTestHoleP.java delete mode 100644 nat/src/test/java/net/tomp2p/holep/HolePStressTest.java delete mode 100644 nat/src/test/java/net/tomp2p/holep/IntegrationTestBootstrapBuilder.java delete mode 100644 nat/src/test/java/net/tomp2p/holep/IntegrationTestHolePuncher.java delete mode 100644 nat/src/test/java/net/tomp2p/relay/TestRelay.java delete mode 100644 nat/src/test/java/net/tomp2p/relay/TestRelayReplication.java delete mode 100644 nat/src/test/java/net/tomp2p/relay/buffer/TestMessageBuffer.java diff --git a/all/pom.xml b/all/pom.xml index e2de6cf95..1affd99b1 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -32,11 +32,6 @@ tomp2p-nat ${project.version} - - ${project.groupId} - tomp2p-android - ${project.version} - ${project.groupId} tomp2p-replication diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index 0f929c2dd..000000000 --- a/android/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.classpath -.project -.settings -.checkstyle -.cache -.idea -*.iml -*~ -p2p.log -/target -/bin \ No newline at end of file diff --git a/android/pom.xml b/android/pom.xml deleted file mode 100644 index c6cf79159..000000000 --- a/android/pom.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - 4.0.0 - - - net.tomp2p - tomp2p-parent - 5.0-Beta9-SNAPSHOT - - - tomp2p-android - TomP2P android - jar - - - UTF-8 - - - - - Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 - - - - - - ${project.groupId} - tomp2p-nat - ${project.version} - - - - ch.qos.logback - logback-classic - true - - - - - com.ganyo - gcm-server - 1.0.2 - - - - - junit - junit - 4.11 - test - - - - ${project.groupId} - tomp2p-dht - ${project.version} - test - - - - - - - - src/test/resources - - - - - diff --git a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClient.java b/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClient.java deleted file mode 100644 index 0924d19bd..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClient.java +++ /dev/null @@ -1,119 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.concurrent.atomic.AtomicBoolean; - -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.relay.buffer.BufferedRelayClient; -import net.tomp2p.rpc.RPC.Commands; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * When an Android device is behind a NAT, this class Holds a connection to one relay. It has - * additional capabilities like retrieving the buffer. - * - * @author Nico Rutishauser - * - */ -public class AndroidRelayClient extends BufferedRelayClient { - - private static final Logger LOG = LoggerFactory.getLogger(AndroidRelayClient.class); - /** - * The maximum number of attempts to reach the relay peer. If the counter exceeds this limit, the relay is - * declared as unreachable - */ - private static final int MAX_FAIL_COUNT = 5; - - private int reachRelayFailCounter = 0; - private final AtomicBoolean shutdown; - - public AndroidRelayClient(PeerAddress relayAddress, Peer peer) { - super(relayAddress, peer); - this.shutdown = new AtomicBoolean(false); - } - - @Override - public FutureResponse sendToRelay(Message message) { - if (shutdown.get()) { - return new FutureResponse(message).failed("Relay connection is already shut down"); - } - - // send it over a newly opened connection - return RelayUtils.connectAndSend(peer, message); - } - - /** - * Get the buffer from the relay. This method should be called as soon as the device receives the tickle - * message from the relay over GCM. - * - * @return when the buffer request is done - */ - public FutureDone sendBufferRequest() { - if (shutdown.get()) { - return new FutureDone().failed("Relay connection is already shut down"); - } - - LOG.debug("Sending buffer request to relay {}", relayAddress()); - final FutureDone futureDone = new FutureDone(); - - Message message = new Message().recipient(relayAddress()).sender(peer.peerBean().serverPeerAddress()) - .command(Commands.RELAY.getNr()).type(Type.REQUEST_4).version(peer.connectionBean().p2pId()) - .keepAlive(false); - - FutureResponse response = sendToRelay(message); - response.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse futureResponse) throws Exception { - if (futureResponse.isSuccess()) { - // reset the fail counter - reachRelayFailCounter = 0; - - LOG.debug("Successfully got the buffer from relay {}", relayAddress()); - onReceiveMessageBuffer(futureResponse.responseMessage(), futureDone); - } else { - LOG.error("Cannot get the buffer from relay {}. Reason: {}", relayAddress(), - futureResponse.failedReason()); - futureDone.failed(futureResponse); - failedToContactRelay(); - } - } - }); - - return futureDone; - } - - @Override - public FutureDone shutdown() { - shutdown.set(true); - // else, nothing to do - return new FutureDone().done(); - } - - private void failedToContactRelay() { - LOG.warn("Failed to contact the relay peer. Increase the counter to detect long-term disconnections"); - reachRelayFailCounter++; - if (reachRelayFailCounter > MAX_FAIL_COUNT) { - LOG.error("The relay {} was not reachable for {} send attempts", relayAddress(), reachRelayFailCounter); - notifyCloseListeners(); - } - } - - @Override - public void onMapUpdateFailed() { - failedToContactRelay(); - } - - @Override - public void onMapUpdateSuccess() { - // reset the couter - reachRelayFailCounter = 0; - } -} diff --git a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClientConfig.java b/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClientConfig.java deleted file mode 100644 index 14ace92b1..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayClientConfig.java +++ /dev/null @@ -1,112 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.message.Message; -import net.tomp2p.message.NeighborSet; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayClient; -import net.tomp2p.relay.RelayClientConfig; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.RelayUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AndroidRelayClientConfig extends RelayClientConfig { - - private final static Logger LOG = LoggerFactory.getLogger(AndroidRelayClientConfig.class); - - private final String registrationId; - private Collection gcmServers; - private final AtomicBoolean gcmServersChanged; - - /** - * Creates an Android relay configuration. The messages at the relayed peer are not buffered. - * - * @param registrationId the Google Cloud Messaging registration ID. This can be obtained on an Android - * device by providing the correct senderID. The registration ID is unique for each device for - * each senderID. - */ - public AndroidRelayClientConfig(String registrationId) { - this(registrationId, 60); - } - - public AndroidRelayClientConfig(String registrationId, int peerMapUpdateIntervalS) { - super(RelayType.ANDROID, peerMapUpdateIntervalS, 120, 2); - - assert registrationId != null; - this.registrationId = registrationId; - this.gcmServers = Collections.emptySet(); - this.gcmServersChanged = new AtomicBoolean(false); - } - - /** - * Only used for {@link RelayClientConfig#ANDROID}
- * - * @return the GCM registration ID. If this peer is an unreachable Android device, this value needs to be - * provided. - */ - public String registrationId() { - return registrationId; - } - - /** - * @return a collection of known GCM servers which are known to be able to send GCM messages. A GCM server - * can - * be configured by setting {@link PeerBuilderNAT#gcmAuthenticationKey(String)}. - */ - public Collection gcmServers() { - return gcmServers; - } - - /** - * Defines well-known peers that have the ability to send messages over Google Cloud Messaging. If an - * empty list or null is provided, the relays try to send it by themselves or deny the relay connection. - * - * @param gcmServers a set of peers that can send GCM messages - * @return this instance - */ - public RelayClientConfig gcmServers(Set gcmServers) { - if (gcmServers == null) { - this.gcmServers = Collections.emptySet(); - } else { - this.gcmServers = gcmServers; - this.gcmServersChanged.set(true); - } - return this; - } - - @Override - public void prepareSetupMessage(Message message) { - // add the registration ID, the GCM authentication key and the map update interval - message.buffer(RelayUtils.encodeString(registrationId)); - message.intValue(peerMapUpdateInterval()); - - if(gcmServers != null && !gcmServers.isEmpty()) { - // provide gcm servers at startup, later they will be updated using the map update task - message.neighborsSet(new NeighborSet(-1, gcmServers)); - } - } - - @Override - public void prepareMapUpdateMessage(Message message) { - // if GCM servers changed, send them again to the relay - if(gcmServersChanged.get()) { - LOG.debug("Sending updated GCM server list as well"); - message.neighborsSet(new NeighborSet(-1, gcmServers)); - gcmServersChanged.set(false); - } - } - - @Override - public BaseRelayClient createClient(PeerConnection connection, Peer peer) { - return new AndroidRelayClient(connection.remotePeer(), peer); - } -} diff --git a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServer.java b/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServer.java deleted file mode 100644 index af5aa748d..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServer.java +++ /dev/null @@ -1,85 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.concurrent.atomic.AtomicLong; - -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.android.gcm.FutureGCM; -import net.tomp2p.relay.android.gcm.IGCMSender; -import net.tomp2p.relay.android.gcm.RemoteGCMSender; -import net.tomp2p.relay.buffer.BufferedRelayServer; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Manages the mapping between a peer address and the registration id. The registration id is sent by the - * mobile device when the relay is set up. - * - * @author Nico Rutishauser - * - */ -public class AndroidRelayServer extends BufferedRelayServer { - - private static final Logger LOG = LoggerFactory.getLogger(AndroidRelayServer.class); - - private final String registrationId; - private final IGCMSender sender; - private final int mapUpdateIntervalMS; - private final AtomicLong lastUpdate; - - public AndroidRelayServer(Peer peer, PeerAddress unreachablePeer, MessageBufferConfiguration bufferConfig, - String registrationId, IGCMSender sender, int mapUpdateIntervalS) { - super(peer, unreachablePeer, RelayType.ANDROID, bufferConfig); - this.registrationId = registrationId; - this.sender = sender; - - // stretch the update interval by factor 1.5 to be tolerant for slow messages - this.mapUpdateIntervalMS = (int) (mapUpdateIntervalS * 1000 * 1.5); - this.lastUpdate = new AtomicLong(System.currentTimeMillis()); - } - - @Override - public void onBufferFull() { - sender.send(new FutureGCM(registrationId, relayPeerId(), unreachablePeerAddress())); - } - - @Override - protected void onBufferCollected() { - // the mobile device seems to be alive - lastUpdate.set(System.currentTimeMillis()); - } - - @Override - protected void peerMapUpdated(Message requestMessage, Message preparedResponse) { - // take this event as an indicator that the mobile device is online - lastUpdate.set(System.currentTimeMillis()); - LOG.trace("Timeout for {} refreshed", registrationId); - - if (requestMessage.neighborsSet(1) != null && sender instanceof RemoteGCMSender) { - // update the GCM servers - RemoteGCMSender remoteGCMSender = (RemoteGCMSender) sender; - remoteGCMSender.gcmServers(requestMessage.neighborsSet(1).neighbors()); - LOG.debug("Received update of the GCM servers"); - } - - super.peerMapUpdated(requestMessage, preparedResponse); - } - - @Override - protected boolean isAlive() { - // Check if the mobile device is still alive by checking its last update time. - if (lastUpdate.get() + mapUpdateIntervalMS > System.currentTimeMillis()) { - LOG.trace("Device {} seems to be alive", registrationId); - return true; - } else { - LOG.warn("Device {} did not send any messages for a long time", registrationId); - notifyOfflineListeners(); - return false; - } - } - -} diff --git a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServerConfig.java b/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServerConfig.java deleted file mode 100644 index dd2ed60f5..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/AndroidRelayServerConfig.java +++ /dev/null @@ -1,111 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.Collection; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.Responder; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.RelayServerConfig; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.relay.android.gcm.GCMSenderRPC; -import net.tomp2p.relay.android.gcm.IGCMSender; -import net.tomp2p.relay.android.gcm.RemoteGCMSender; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AndroidRelayServerConfig extends RelayServerConfig { - - private static final Logger LOG = LoggerFactory.getLogger(AndroidRelayServerConfig.class); - - private final MessageBufferConfiguration bufferConfig; - private final String gcmAuthenticationKey; - private final int gcmRetries; - protected IGCMSender gcmSender; - - /** - * Creates an Android relay server configuration that is able to send GCM messages itself - * - * @param gcmAuthenticationKey the api key / authentication token for Google Cloud Messaging. The key - * can be obtained through Google's developer console. The key should be kept secret. - * @param gcmRetries how many times the GCM message should be resent before giving up. Normal ranges are 1-5 - * @param bufferConfig the buffer behavior before sending a GCM message to the Android device - */ - public AndroidRelayServerConfig(String gcmAuthenticationKey, int gcmRetries, MessageBufferConfiguration bufferConfig) { - this.gcmAuthenticationKey = gcmAuthenticationKey; - this.gcmRetries = gcmRetries; - this.bufferConfig = bufferConfig; - } - - /** - * Creates an Android relay server config that is not able to send GCM messages itself. - * Connecting unreachable peers need to provide at least one known other peer that has the ability to send - * GCM messages. - * - * @param bufferConfig the buffer behavior before sending a GCM message to the Android device (over a - * {@link RemoteGCMSender}). - */ - public AndroidRelayServerConfig(MessageBufferConfiguration bufferConfig) { - this(null, 0, bufferConfig); - } - - @Override - public void start(Peer peer) { - if (gcmAuthenticationKey != null) { - gcmSender = new GCMSenderRPC(peer, gcmAuthenticationKey, gcmRetries); - LOG.debug("GCM server started on {}", peer.peerAddress()); - } - } - - @Override - public BaseRelayServer createServer(Message message, PeerConnection peerConnection, Responder responder, Peer peer) { - /** The registration ID */ - if (message.bufferList().size() < 1) { - LOG.error("Device {} did not send any GCM registration id", peerConnection.remotePeer()); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - - String registrationId = RelayUtils.decodeString(message.buffer(0)); - if (registrationId == null) { - LOG.error("Cannot decode the registrationID from the message"); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - - /** Update interval */ - Integer mapUpdateInterval = message.intAt(1); - if (mapUpdateInterval == null) { - LOG.error("Android device did not send the peer map update interval."); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - - /** GCM handing */ - IGCMSender sender = null; - if (message.neighborsSetList().isEmpty()) { - // no known GCM servers, use GCM ability of this peer - sender = gcmSender; - if (sender == null) { - LOG.error("This relay is unable to serve unreachable Android devices because no GCM Authentication Key is configured"); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - } else { - // device sent well-known GCM servers to use - Collection gcmServers = message.neighborsSet(0).neighbors(); - sender = new RemoteGCMSender(peer, gcmServers); - } - - LOG.debug("Hello Android device! You'll be relayed over GCM. {}", message); - AndroidRelayServer androidServer = new AndroidRelayServer(peer, peerConnection.remotePeer(), bufferConfig, - registrationId, sender, mapUpdateInterval); - responder.response(createResponse(message, Type.OK, peer.peerBean().serverPeerAddress())); - return androidServer; - } -} diff --git a/android/src/main/java/net/tomp2p/relay/android/gcm/FutureGCM.java b/android/src/main/java/net/tomp2p/relay/android/gcm/FutureGCM.java deleted file mode 100644 index c61b1228c..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/gcm/FutureGCM.java +++ /dev/null @@ -1,40 +0,0 @@ -package net.tomp2p.relay.android.gcm; - -import net.tomp2p.futures.FutureDone; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; - -public class FutureGCM extends FutureDone { - - private final String registrationId; - private final Number160 senderId; - private final PeerAddress recipient; - - public FutureGCM(String registrationId, Number160 senderId, PeerAddress recipient) { - self(this); - this.registrationId = registrationId; - this.senderId = senderId; - this.recipient = recipient; - } - - /** - * The recipient - */ - public String registrationId() { - return registrationId; - } - - /** - * The relay that sent the GCM request (where the messages are buffered) - */ - public Number160 senderId() { - return senderId; - } - - /** - * The unreachable peer receiving the GCM - */ - public PeerAddress recipient() { - return recipient; - } -} diff --git a/android/src/main/java/net/tomp2p/relay/android/gcm/GCMSenderRPC.java b/android/src/main/java/net/tomp2p/relay/android/gcm/GCMSenderRPC.java deleted file mode 100644 index f9b17d385..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/gcm/GCMSenderRPC.java +++ /dev/null @@ -1,140 +0,0 @@ -package net.tomp2p.relay.android.gcm; - -import java.io.IOException; -import java.util.concurrent.ScheduledExecutorService; - -import net.tomp2p.connection.Dispatcher; -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.Responder; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.rpc.DispatchHandler; -import net.tomp2p.rpc.RPC; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.android.gcm.server.Result; -import com.google.android.gcm.server.Sender; - -/** - * This RPC is dedicated to send messages over Google Cloud Messaging. It's only used if - * {@link RelayType#ANDROID} devices are relayed in the network. The GCM server authentication keys should not - * be distributed in the whole network (because of privacy) and thus, this RPC acts as the key-holder and - * server to send GCM messages. Relayed Android devices need to provide the {@link PeerAddress} of one or - * multiple GCMSenders of this kind. - * - * @author Nico Rutishauser - * - */ -public class GCMSenderRPC extends DispatchHandler implements IGCMSender { - - private static final Logger LOG = LoggerFactory.getLogger(GCMSenderRPC.class); - - private final Sender sender; - private final int retries; - private final ScheduledExecutorService executor; - - public GCMSenderRPC(final Peer peer, String authenticationKey, int retries) { - super(peer.peerBean(), peer.connectionBean()); - this.sender = new Sender(authenticationKey); - this.retries = retries; - this.executor = peer.connectionBean().timer(); - register(RPC.Commands.GCM.getNr()); - } - - /** - * This method is called from the {@link Dispatcher} and handles GCM requests - * - * REQUEST_1 = forward the GCM request to the mobile device.
- * - * @param message - * @param peerConnection - * @param sign - * @param responder - */ - @Override - public void handleResponse(final Message message, final PeerConnection peerConnection, final boolean sign, - final Responder responder) throws Exception { - LOG.warn("Received GCM message {}", message); - if (message.type() == Message.Type.REQUEST_1 && message.command() == RPC.Commands.GCM.getNr()) { - // the message reached the relay peer - LOG.debug("Forwarding tickle message over GCM"); - handleGCMForward(message, responder); - } else { - LOG.warn("Received invalid GCM message {}", message); - throw new IllegalArgumentException("Message content is wrong"); - } - } - - private void handleGCMForward(final Message message, final Responder responder) { - if (message.bufferList().isEmpty()) { - LOG.error("GCM message does not contain the registrationID"); - responder.response(createResponseMessage(message, Type.EXCEPTION)); - return; - } - - String registrationId = RelayUtils.decodeString(message.buffer(0)); - if(registrationId == null || registrationId.isEmpty()) { - LOG.error("RegistrationID of device cannot be read from message"); - responder.response(createResponseMessage(message, Type.EXCEPTION)); - return; - } - - FutureGCM futureGCM = new FutureGCM(registrationId, message.sender().peerId(), message.recipient()); - send(futureGCM); - futureGCM.addListener(new BaseFutureAdapter() { - - @Override - public void operationComplete(FutureGCM future) throws Exception { - if (future.isSuccess()) { - LOG.debug("Successfully sent message over GCM"); - responder.response(createResponseMessage(message, Type.OK)); - } else { - LOG.debug("Could not send message over GCM"); - responder.response(createResponseMessage(message, Type.EXCEPTION)); - } - } - }); - } - - @Override - public void send(final FutureGCM futureGCM) { - // the collapse key is the relay's peerId - final String registrationId = futureGCM.registrationId(); - final com.google.android.gcm.server.Message tickleMessage = new com.google.android.gcm.server.Message.Builder() - .collapseKey(futureGCM.senderId().toString()).delayWhileIdle(false).build(); - - // start in a separate thread since the sender is blocking - executor.submit(new Runnable() { - @Override - public void run() { - try { - LOG.debug("Send GCM message to the device {}", registrationId); - Result result = sender.send(tickleMessage, registrationId, retries); - if (result.getMessageId() == null) { - LOG.error("Could not send the tickle messge. Reason: {}", result.getErrorCodeName()); - futureGCM.failed("Cannot send message over GCM. Reason: " + result.getErrorCodeName()); - } else { - LOG.debug("Successfully sent the message over GCM"); - futureGCM.done(); - if (result.getCanonicalRegistrationId() != null) { - LOG.debug("Update the registration id {} to canonical name {}", registrationId, - result.getCanonicalRegistrationId()); - // TODO update the registration ID - // registrationId = result.getCanonicalRegistrationId(); - } - } - } catch (IOException e) { - LOG.error("Cannot send tickle message to device {}", registrationId, e); - futureGCM.failed(e); - } - } - }, "Send-GCM-Tickle-Message"); - } -} diff --git a/android/src/main/java/net/tomp2p/relay/android/gcm/IGCMSender.java b/android/src/main/java/net/tomp2p/relay/android/gcm/IGCMSender.java deleted file mode 100644 index d68d7f972..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/gcm/IGCMSender.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.tomp2p.relay.android.gcm; - -public interface IGCMSender { - - /** - * Tickle the device through Google Cloud Messaging - * - * @param futureGCM the tickle request containing also the buffered messages - */ - void send(FutureGCM futureGCM); -} diff --git a/android/src/main/java/net/tomp2p/relay/android/gcm/RemoteGCMSender.java b/android/src/main/java/net/tomp2p/relay/android/gcm/RemoteGCMSender.java deleted file mode 100644 index e60327707..000000000 --- a/android/src/main/java/net/tomp2p/relay/android/gcm/RemoteGCMSender.java +++ /dev/null @@ -1,87 +0,0 @@ -package net.tomp2p.relay.android.gcm; - -import java.util.ArrayList; -import java.util.Collection; - -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.rpc.RPC; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Send GCM messages to other well-known peers (direct messages) which then send it to the Google Cloud - * Messaging servers. This is basically used if one of the relay peers serving an Android device does not have - * the GCM authentication key. This key is needed to send messages over GCM and can be obtained at Google's - * developer console. - * - * @author Nico Rutishauser - * - */ -public class RemoteGCMSender implements IGCMSender { - - private static final Logger LOG = LoggerFactory.getLogger(RemoteGCMSender.class); - private static final int TIMEOUT_MS = 10000; - - private final Peer peer; - private Collection gcmServers; - - public RemoteGCMSender(Peer peer, Collection gcmServers) { - this.gcmServers = gcmServers; - this.peer = peer; - } - - @Override - public void send(final FutureGCM futureGCM) { - final Collection copy; - synchronized (gcmServers) { - copy = new ArrayList(gcmServers); - } - - if (copy.isEmpty()) { - LOG.error("Cannot send GCM messages because no GCM server is known"); - futureGCM.failed("Cannot send GCM messages because no GCM server is known"); - return; - } - - // send in separate thread to not block the caller - peer.connectionBean().timer().submit(new Runnable() { - @Override - public void run() { - // send to one of the servers - for (PeerAddress gcmServer : copy) { - LOG.debug("Try sending message to {}", gcmServer); - Message message = new Message().recipient(gcmServer).sender(peer.peerAddress()) - .command(RPC.Commands.GCM.getNr()).type(Type.REQUEST_1).version(peer.p2pId()) - .buffer(RelayUtils.encodeString(futureGCM.registrationId())); - - FutureResponse futureResponse = RelayUtils.connectAndSend(peer, message); - if (futureResponse.awaitUninterruptibly(TIMEOUT_MS) && futureResponse.isSuccess()) { - LOG.debug("GCM server {} sent the message successfully", gcmServer); - return; - } else { - LOG.debug("GCM server {} did not accept the message. Reason: {}", futureResponse.failedReason()); - // go to next server - } - } - - LOG.error("Could not send the message to any of the GCM servers"); - futureGCM.failed("Could not send the message to any of the GCM servers"); - } - }); - } - - /** - * Update the gcm servers - */ - public void gcmServers(Collection gcmServers) { - synchronized (this.gcmServers) { - this.gcmServers = gcmServers; - } - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/AssertingSlowPeerFilter.java b/android/src/test/java/net/tomp2p/relay/android/AssertingSlowPeerFilter.java deleted file mode 100644 index 9e31fb12d..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/AssertingSlowPeerFilter.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.tomp2p.relay.android; - -import net.tomp2p.p2p.SlowPeerFilter; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; - -import org.junit.Assert; - -/** - * Not only checks the slow flag, but also checks if the request targets this very same peer. If it does, the - * request is allowed. - * - * @author Nico - * - */ -public class AssertingSlowPeerFilter extends SlowPeerFilter { - - private final Number160 slowPeer; - - public AssertingSlowPeerFilter(Number160 slowPeer) { - this.slowPeer = slowPeer; - } - - @Override - public boolean rejectDirectHit(PeerAddress peerAddress) { - boolean reject = super.rejectDirectHit(peerAddress); - if (!reject && peerAddress.peerId().equals(slowPeer)) { - Assert.fail("Should have filtered slow peer"); - } - return reject; - } - - @Override - public boolean rejectPotentialHit(PeerAddress peerAddress) { - boolean reject = super.rejectPotentialHit(peerAddress); - if (!reject && peerAddress.peerId().equals(slowPeer)) { - Assert.fail("Should have filtered slow peer"); - } - return reject; - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClient.java b/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClient.java deleted file mode 100644 index 7ae8c02a1..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClient.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.tomp2p.relay.android; - -import net.tomp2p.futures.FutureDone; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MockedAndroidRelayClient extends AndroidRelayClient { - - private static final Logger LOG = LoggerFactory.getLogger(MockedAndroidRelayClient.class); - private long bufferReceptionDelay = 0L; - - public MockedAndroidRelayClient(PeerAddress relayAddress, Peer peer) { - super(relayAddress, peer); - } - - public void bufferReceptionDelay(long bufferReceptionDelay) { - this.bufferReceptionDelay = bufferReceptionDelay; - } - - @Override - public void onReceiveMessageBuffer(Message responseMessage, FutureDone futureDone) { - if (bufferReceptionDelay > 0) { - LOG.debug("Delayed buffer reception"); - try { - Thread.sleep(bufferReceptionDelay); - } catch (InterruptedException e) { - // ignore - } - } - super.onReceiveMessageBuffer(responseMessage, futureDone); - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClientConfig.java b/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClientConfig.java deleted file mode 100644 index 8c55ff814..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayClientConfig.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.HashMap; -import java.util.Map; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayClient; - -public class MockedAndroidRelayClientConfig extends AndroidRelayClientConfig { - - public static final String DUMMY_GCM_API_KEY = "dummy-gcm-key"; - private final Map clientList; - - public MockedAndroidRelayClientConfig(int peerMapUpdateIntervalS) { - super(DUMMY_GCM_API_KEY, peerMapUpdateIntervalS); - this.clientList = new HashMap(); - } - - @Override - public BaseRelayClient createClient(PeerConnection connection, Peer peer) { - MockedAndroidRelayClient client = new MockedAndroidRelayClient(connection.remotePeer(), peer); - clientList.put(peer.peerAddress(), client); - return client; - } - - /** - * Notifies the unreachable peer directly without sending a real GCM message - */ - public void mockGCMNotification(PeerAddress unreachablePeer) { - if(clientList.containsKey(unreachablePeer)) { - clientList.get(unreachablePeer).sendBufferRequest(); - } else { - throw new IllegalStateException("No client with PeerAddress " + unreachablePeer + " connected"); - } - } - - public MockedAndroidRelayClient getClient(PeerAddress clientAddress) { - return clientList.get(clientAddress); - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayServerConfig.java b/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayServerConfig.java deleted file mode 100644 index f3c82afb6..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/MockedAndroidRelayServerConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.tomp2p.relay.android; - -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; - -/** - * Mocks the GCM functionality for testing purpose - * - * @author Nico Rutishauser - * - */ -public class MockedAndroidRelayServerConfig extends AndroidRelayServerConfig { - - private final MockedAndroidRelayClientConfig client; - - public MockedAndroidRelayServerConfig(MessageBufferConfiguration bufferConfig, MockedAndroidRelayClientConfig client) { - super(bufferConfig); - this.client = client; - } - - @Override - public void start(Peer peer) { - gcmSender = new MockedGCMSender(peer, client); - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/MockedGCMSender.java b/android/src/test/java/net/tomp2p/relay/android/MockedGCMSender.java deleted file mode 100644 index 937ccf6a6..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/MockedGCMSender.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.tomp2p.relay.android; - -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.android.gcm.FutureGCM; -import net.tomp2p.relay.android.gcm.GCMSenderRPC; -import net.tomp2p.relay.android.gcm.IGCMSender; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MockedGCMSender extends GCMSenderRPC implements IGCMSender { - - private static final Logger LOG = LoggerFactory.getLogger(MockedGCMSender.class); - private static final long DEFAULT_GCM_MOCK_DELAY_MS = 1500; - private static final String DUMMY_REGISTRATION_ID = "dummy-registration-id"; - - private final MockedAndroidRelayClientConfig client; - - public MockedGCMSender(Peer peer, MockedAndroidRelayClientConfig client) { - super(peer, DUMMY_REGISTRATION_ID, 0); - this.client = client; - LOG.debug("Mocked GCM sender started"); - } - - @Override - public void send(final FutureGCM futureGCM) { - new Thread(new Runnable() { - @Override - public void run() { - try { - Thread.sleep(DEFAULT_GCM_MOCK_DELAY_MS); - } catch (InterruptedException e) { - // ignore - } - PeerAddress recipient = futureGCM.recipient(); - client.mockGCMNotification(recipient); - LOG.debug("Mocked sending a message to the unreachable peer {}", recipient); - } - }).start(); - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/TestAndroidRelay.java b/android/src/test/java/net/tomp2p/relay/android/TestAndroidRelay.java deleted file mode 100644 index 42c7f8747..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/TestAndroidRelay.java +++ /dev/null @@ -1,221 +0,0 @@ -package net.tomp2p.relay.android; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Random; - -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.dht.PutBuilder; -import net.tomp2p.nat.FutureRelayNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.p2p.RequestP2PConfiguration; -import net.tomp2p.p2p.RoutingConfiguration; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number640; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; -import net.tomp2p.storage.Data; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class TestAndroidRelay { - - private final Random rnd = new Random(42); - private final TestRelay testRelay; - - private final MockedAndroidRelayClientConfig clientConfig; - private final MockedAndroidRelayServerConfig serverConfig; - - @SuppressWarnings("rawtypes") - @Parameterized.Parameters(name = "{0}") - public static Collection data() throws Exception { - return Arrays.asList(new Object[][] { - { new MessageBufferConfiguration().bufferAgeLimit(2000).bufferCountLimit(10).bufferSizeLimit(Long.MAX_VALUE), 10 }, - { new MessageBufferConfiguration().bufferAgeLimit(Long.MAX_VALUE).bufferCountLimit(1).bufferSizeLimit(Long.MAX_VALUE), 10 } } - ); - } - - public TestAndroidRelay(MessageBufferConfiguration bufferConfig, int peerMapIntervalS) { - clientConfig = new MockedAndroidRelayClientConfig(peerMapIntervalS); - serverConfig = new MockedAndroidRelayServerConfig(bufferConfig, clientConfig); - testRelay = new TestRelay(RelayType.ANDROID, serverConfig, clientConfig); - } - - @Test - public void testSetupRelayPeers() throws Exception { - testRelay.testSetupRelayPeers(); - } - - @Test - public void testBoostrap() throws Exception { - testRelay.testBoostrap(); - } - - /** - * Tests sending a message from an unreachable peer to another unreachable peer - */ - @Test - public void testRelaySendDirect() throws Exception { - testRelay.testRelaySendDirect(); - } - - /** - * Tests sending a message from a reachable peer to an unreachable peer - */ - @Test - public void testRelaySendDirect2() throws Exception { - testRelay.testRelaySendDirect2(); - } - - /** - * Tests sending a message from an unreachable peer to a reachable peer - */ - @Test - public void testRelaySendDirect3() throws Exception { - testRelay.testRelaySendDirect3(); - } - - @Test - public void testRelayRouting() throws Exception { - testRelay.testRelayRouting(); - } - - @Test - public void testNoRelayDHT() throws Exception { - testRelay.testNoRelayDHT(); - } - - @Test - public void testRelayDHTSimple() throws Exception { - testRelay.testRelayDHTSimple(); - } - - @Test - public void testRelayDHT() throws Exception { - testRelay.testRelayDHT(); - } - - @Test - public void testRelayDHTPutGet() throws Exception { - testRelay.testRelayDHTPutGet(); - } - - @Test - public void testRelayDHTPutGet2() throws Exception { - testRelay.testRelayDHTPutGet2(); - } - - @Test - public void testRelayDHTPutGetSigned() throws Exception { - testRelay.testRelayDHTPutGetSigned(); - } - - @Test - public void testVeryFewPeers() throws Exception { - testRelay.testVeryFewPeers(); - } - - @Test - public void testRelaySlowPeer() throws Exception { - // make the timeout very small, such that the mobile device is too slow to answer the request - int slowResponseTimeoutS = 2; - - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(RelayType.ANDROID, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // wait to be about in the middle of two map updates - Thread.sleep(clientConfig.peerMapUpdateInterval() * 500); - // block message buffers transmitted through the map update task - clientConfig.getClient(unreachablePeer.peerAddress()).bufferReceptionDelay(slowResponseTimeoutS * 1200); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - PutBuilder builder = peers[8].put(unreachablePeer.peerID()).data(new Data("hello")).routingConfiguration(r).requestP2PConfiguration(rp); - builder.slowResponseTimeoutSeconds(slowResponseTimeoutS); - FuturePut futurePut = builder.start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - - System.err.println(futurePut.failedReason()); - // should be run into a timeout - Assert.assertFalse(futurePut.isSuccess()); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - - @Test - public void testSlowPeerFilter() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(RelayType.ANDROID, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - Number160 contentKey = Number160.createHash(142); - Number160 domainKey = Number160.createHash(921); - AssertingSlowPeerFilter filter = new AssertingSlowPeerFilter(unreachablePeer.peerID()); - - // double-check that the address is slow - Assert.assertTrue(unreachablePeer.peerAddress().isSlow()); - - System.err.println("Start put----"); - FuturePut futurePut = peers[0].put(unreachablePeer.peerID()).data(contentKey, new Data("hello"), Number160.ZERO).domainKey(domainKey).addPostRoutingFilter(filter).start().awaitUninterruptibly(); - futurePut.futureRequests().awaitUninterruptibly(); - Assert.assertTrue(futurePut.isSuccess()); - System.err.println("End put----"); - - // The relayed peer should not be asked to store the content - Assert.assertFalse(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), domainKey, contentKey, Number160.ZERO))); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } -} diff --git a/android/src/test/java/net/tomp2p/relay/android/TestRelay.java b/android/src/test/java/net/tomp2p/relay/android/TestRelay.java deleted file mode 100644 index 44f55168e..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/TestRelay.java +++ /dev/null @@ -1,878 +0,0 @@ -package net.tomp2p.relay.android; - -import java.net.InetAddress; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; - -import net.tomp2p.dht.FutureGet; -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.nat.FutureRelayNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.p2p.RequestP2PConfiguration; -import net.tomp2p.p2p.RoutingConfiguration; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number320; -import net.tomp2p.peers.Number640; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.relay.BaseRelayClient; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.FutureRelay; -import net.tomp2p.relay.RelayClientConfig; -import net.tomp2p.relay.RelayServerConfig; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; -import net.tomp2p.relay.tcp.TCPRelayServerConfig; -import net.tomp2p.relay.tcp.buffered.BufferedTCPRelayClientConfig; -import net.tomp2p.relay.tcp.buffered.BufferedTCPRelayServerConfig; -import net.tomp2p.rpc.DispatchHandler; -import net.tomp2p.rpc.ObjectDataReply; -import net.tomp2p.storage.Data; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -/* - * This is a copy of TestRelay from tomp2p-nat. Maven does not allow to depend on test code from other modules: - * http://jira.codehaus.org/browse/MNG-3559 - */ - -@RunWith(Parameterized.class) -public class TestRelay { - - private final RelayType relayType; - private final RelayServerConfig serverConfig; - private final RelayClientConfig clientConfig; - - @SuppressWarnings("rawtypes") - @Parameterized.Parameters - public static Collection data() throws Exception { - MessageBufferConfiguration ageLimit = new MessageBufferConfiguration().bufferAgeLimit(2000).bufferCountLimit(Integer.MAX_VALUE).bufferSizeLimit(Long.MAX_VALUE); - MessageBufferConfiguration singleBuf = new MessageBufferConfiguration().bufferAgeLimit(Long.MAX_VALUE).bufferCountLimit(1).bufferSizeLimit(Long.MAX_VALUE); - - return Arrays.asList(new Object[][] { - { RelayType.OPENTCP, new TCPRelayServerConfig(), new TCPRelayClientConfig().peerMapUpdateInterval(5) }, - { RelayType.BUFFERED_OPENTCP, new BufferedTCPRelayServerConfig(ageLimit), new BufferedTCPRelayClientConfig().peerMapUpdateInterval(5) }, - { RelayType.BUFFERED_OPENTCP, new BufferedTCPRelayServerConfig(singleBuf), new BufferedTCPRelayClientConfig().peerMapUpdateInterval(5) } }); - } - - public TestRelay(RelayType relayType, RelayServerConfig serverConfig, RelayClientConfig clientConfig) { - this.relayType = relayType; - this.serverConfig = serverConfig; - this.clientConfig = clientConfig; - } - - private void waitMapUpdate() throws InterruptedException { - Thread.sleep(clientConfig.peerMapUpdateInterval() * 1000); - } - - @Test - public void testSetupRelayPeers() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 200; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(5000).start(); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - // Check if flags are set correctly - Assert.assertTrue(unreachablePeer.peerAddress().isRelayed()); - Assert.assertFalse(unreachablePeer.peerAddress().isFirewalledTCP()); - Assert.assertFalse(unreachablePeer.peerAddress().isFirewalledUDP()); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testBoostrap() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 10; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(5000).start(); - PeerAddress upa = unreachablePeer.peerBean().serverPeerAddress(); - upa = upa.changeFirewalledTCP(true).changeFirewalledUDP(true); - unreachablePeer.peerBean().serverPeerAddress(upa); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - // find neighbors again - futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - boolean otherPeersHaveRelay = false; - - for (Peer peer : peers) { - if (peer.peerBean().peerMap().allOverflow().contains(unreachablePeer.peerAddress())) { - for (PeerAddress pa : peer.peerBean().peerMap().allOverflow()) { - if (pa.peerId().equals(unreachablePeer.peerID())) { - if (pa.peerSocketAddresses().size() > 0) { - otherPeersHaveRelay = true; - } - System.err.println("-->" + pa.peerSocketAddresses()); - System.err.println("relay=" + pa.isRelayed()); - } - } - System.err.println("check 1! " + peer.peerAddress()); - } - - } - Assert.assertTrue(otherPeersHaveRelay); - - // wait for maintenance - waitMapUpdate(); - - boolean otherPeersMe = false; - for (Peer peer : peers) { - if (peer.peerBean().peerMap().all().contains(unreachablePeer.peerAddress())) { - System.err.println("check 2! " + peer.peerAddress()); - otherPeersMe = true; - } - } - Assert.assertTrue(otherPeersMe); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - /** - * Tests sending a message from an unreachable peer to another unreachable peer - */ - @Test - public void testRelaySendDirect() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer1 = null; - Peer unreachablePeer2 = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1).start(); - FutureRelayNAT fbn = uNat1.startRelay(clientConfig, master.peerAddress()); - fbn.awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - System.out.print("Send direct message to unreachable peer " + unreachablePeer1.peerAddress()); - final String request = "Hello "; - final String response = "World!"; - - final AtomicBoolean test1 = new AtomicBoolean(false); - final AtomicBoolean test2 = new AtomicBoolean(false); - - // final Peer unr = unreachablePeer; - unreachablePeer1.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object obj) throws Exception { - test1.set(obj.equals(request)); - Assert.assertEquals(request.toString(), request); - test2.set(sender.inetAddress().toString().contains("0.0.0.0")); - System.err.println("Got sender:" + sender); - - // this is too late here, so we cannot test this here - // Collection list = new ArrayList(); - // list.add(new PeerSocketAddress(InetAddress.getByName("101.101.101.101"), 101, 101)); - // unr.peerBean().serverPeerAddress(unr.peerBean().serverPeerAddress().changePeerSocketAddresses(list)); - - return response; - } - }); - - unreachablePeer2 = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13338).start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2).start(); - fbn = uNat2.startRelay(clientConfig, peers[42].peerAddress()); - - fbn.awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // prevent rcon - Collection list = unreachablePeer2.peerBean().serverPeerAddress().peerSocketAddresses(); - if (list.size() >= clientConfig.type().maxRelayCount()) { - Iterator iterator = list.iterator(); - iterator.next(); - iterator.remove(); - } - list.add(new PeerSocketAddress(InetAddress.getByName("10.10.10.10"), 10, 10)); - unreachablePeer2.peerBean().serverPeerAddress( - unreachablePeer2.peerBean().serverPeerAddress().changePeerSocketAddresses(list)); - - System.err.println("unreachablePeer1: " + unreachablePeer1.peerAddress()); - System.err.println("unreachablePeer2: " + unreachablePeer2.peerAddress()); - - FutureDirect fd = unreachablePeer2.sendDirect(unreachablePeer1.peerAddress()).object(request).start() - .awaitUninterruptibly(); - System.err.println("got msg from: " + fd.responseMessage().sender()); - Assert.assertEquals(response, fd.object()); - // make sure we did not receive it from the unreachable peer with port 13337 - // System.err.println(fd.getWrappedFuture()); - // TODO: this case is true for relay - // Assert.assertEquals(fd.wrappedFuture().responseMessage().senderSocket().getPort(), 4001); - // TODO: this case is true for rcon - Assert.assertEquals(unreachablePeer1.peerID(), fd.responseMessage().sender().peerId()); - - Assert.assertTrue(test1.get()); - Assert.assertFalse(test2.get()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.responseMessage().sender() - .peerSocketAddresses().size()); - } finally { - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - /** - * Tests sending a message from a reachable peer to an unreachable peer - */ - @Test - public void testRelaySendDirect2() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // setup relay - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - System.out.print("Send direct message to unreachable peer"); - final String request = "Hello "; - final String response = "World!"; - - unreachablePeer.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object request) throws Exception { - Assert.assertEquals(request.toString(), request); - return response; - } - }); - - FutureDirect fd = peers[42].sendDirect(unreachablePeer.peerAddress()).object(request).start() - .awaitUninterruptibly(); - Assert.assertTrue(fd.isSuccess()); - Assert.assertEquals(response, fd.object()); - - // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(unreachablePeer.peerID(), fd.responseMessage().sender().peerId()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - /** - * Tests sending a message from an unreachable peer to a reachable peer - */ - @Test - public void testRelaySendDirect3() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // setup relay - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - System.out.print("Send direct message from unreachable peer"); - final String request = "Hello "; - final String response = "World!"; - - Peer receiver = peers[42]; - receiver.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object request) throws Exception { - Assert.assertEquals(request.toString(), request); - return response; - } - }); - - FutureDirect fd = unreachablePeer.sendDirect(receiver.peerAddress()).object(request).start() - .awaitUninterruptibly(); - Assert.assertEquals(response, fd.object()); - - // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(receiver.peerID(), fd.responseMessage().sender().peerId()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - @Test - public void testRelayRouting() throws Exception { - final Random rnd = new Random(42); - final int nrOfNodes = 8; // test only works if total nr of nodes is < 8 - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerAddress upa = unreachablePeer.peerBean().serverPeerAddress(); - upa = upa.changeFirewalledTCP(true).changeFirewalledUDP(true); - unreachablePeer.peerBean().serverPeerAddress(upa); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay and lower the update interval to 5s - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()); - FutureRelay frNAT = startRelay.awaitUninterruptibly().futureRelay(); - Assert.assertTrue(startRelay.isSuccess()); - - PeerAddress relayPeer = frNAT.relays().iterator().next().relayAddress(); - Peer found = null; - for (Peer p : peers) { - if (p.peerAddress().equals(relayPeer)) { - found = p; - break; - } - } - Assert.assertNotNull(found); - - // wait for at least one map update task (5s) - waitMapUpdate(); - - int nrOfNeighbors = getNeighbors(found).size(); - // we have in total 9 peers, we should find 8 as neighbors - Assert.assertEquals(8, nrOfNeighbors); - - System.err.println("neighbors: " + nrOfNeighbors); - for (BaseRelayClient relay : frNAT.relays()) { - System.err.println("pc:" + relay.relayAddress()); - } - - Assert.assertEquals(clientConfig.type().maxRelayCount(), frNAT.relays().size()); - - // Shut down a peer - peers[nrOfNodes - 1].shutdown().await(); - peers[nrOfNodes - 2].shutdown().await(); - peers[nrOfNodes - 3].shutdown().await(); - - /* - * needed because failure of a node is detected with periodic - * heartbeat and the routing table of the relay peers are also - * updated periodically - */ - waitMapUpdate(); - - Assert.assertEquals(nrOfNeighbors - 3, getNeighbors(found).size()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), frNAT.relays().size()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - @Test - public void testNoRelayDHT() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT slave = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - PeerMapConfiguration pmc = new PeerMapConfiguration(Number160.createHash(rnd.nextInt())); - slave = new PeerBuilderDHT(new PeerBuilder(Number160.ONE).peerMap(new PeerMap(pmc)).ports(13337).start()) - .start(); - printMapStatus(slave, peers); - FuturePut futurePut = peers[8].put(slave.peerID()).data(new Data("hello")).start().awaitUninterruptibly(); - futurePut.futureRequests().awaitUninterruptibly(); - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertFalse(slave.storageLayer().contains( - new Number640(slave.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (slave != null) { - slave.shutdown().await(); - } - } - } - - private void printMapStatus(PeerDHT slave, PeerDHT[] peers) { - for (PeerDHT peer : peers) { - if (peer.peerBean().peerMap().allOverflow().contains(slave.peerAddress())) { - System.err.println("found relayed peer in overflow bag " + peer.peerAddress()); - } - } - - for (PeerDHT peer : peers) { - if (peer.peerBean().peerMap().all().contains(slave.peerAddress())) { - System.err.println("found relayed peer in regular bag " + peer.peerAddress()); - } - } - } - - @Test - public void testRelayDHTSimple() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(1, rnd, 4000); - master = peers[0]; // the relay peer - new PeerBuilderNAT(master.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - uNat.startRelay(clientConfig, master.peerAddress()); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHT() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer, peers); - - FuturePut futurePut = peers[8].put(unreachablePeer.peerID()).data(new Data("hello")).start() - .awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - Assert.assertTrue(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGet() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - // bootstrap - unreachablePeer.peer().bootstrap().peerAddress(master.peerAddress()).start(); - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println("Unreachable: " + unreachablePeer.peerID()); - System.err.println("Relay: " + master.peerID()); - - FuturePut futurePut = peers[8].put(unreachablePeer.peerID()).data(new Data("hello")).routingConfiguration(r) - .requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = peers[8].get(unreachablePeer.peerID()).routingConfiguration(r).requestP2PConfiguration(rp) - .start().awaitUninterruptibly(); - Assert.assertTrue(futureGet.isSuccess()); - - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGet2() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT unreachablePeer1 = null; - PeerDHT unreachablePeer2 = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1.peer()).start(); - FutureRelayNAT fbn1 = uNat1.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn1.isSuccess()); - - unreachablePeer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13338).start()) - .start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2.peer()).start(); - FutureRelayNAT fbn2 = uNat2.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn2.isSuccess()); - - peers[8] = unreachablePeer1; - peers[9] = unreachablePeer2; - UtilsNAT.perfectRouting(peers); - - // wait for relay setup - Thread.sleep(5000); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer1, peers); - printMapStatus(unreachablePeer2, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println(unreachablePeer1.peerID()); // f1 - System.err.println(unreachablePeer2.peerID()); // e7 - - FuturePut futurePut = unreachablePeer1.put(unreachablePeer2.peerID()).data(new Data("hello")) - .routingConfiguration(r).requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer2.storageLayer().contains( - new Number640(unreachablePeer2.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = unreachablePeer1.get(unreachablePeer2.peerID()).routingConfiguration(r) - .requestP2PConfiguration(rp).fastGet(false).start().awaitUninterruptibly(); - // TODO: try peers even if no data found with fastget - System.err.println(futureGet.failedReason()); - Assert.assertTrue(futureGet.isSuccess()); - - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGetSigned() throws Exception { - final Random rnd = new Random(42); - PeerDHT master = null; - PeerDHT unreachablePeer1 = null; - PeerDHT unreachablePeer2 = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); - KeyPair pair1 = gen.generateKeyPair(); - KeyPair pair2 = gen.generateKeyPair(); - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).keyPair(pair1) - .ports(13337).start()).start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1.peer()).start(); - FutureRelayNAT fbn1 = uNat1.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn1.isSuccess()); - - unreachablePeer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).keyPair(pair2) - .ports(13338).start()).start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2.peer()).start(); - FutureRelayNAT fbn2 = uNat2.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn2.isSuccess()); - - peers[8] = unreachablePeer1; - peers[9] = unreachablePeer2; - UtilsNAT.perfectRouting(peers); - - // wait for relay setup - Thread.sleep(5000); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer1, peers); - printMapStatus(unreachablePeer2, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println(unreachablePeer1.peerID()); // ..8bd - System.err.println(unreachablePeer2.peerID()); // ..af3 - - FuturePut futurePut = unreachablePeer1.put(unreachablePeer2.peerID()).data(new Data("hello")).sign() - .routingConfiguration(r).requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer2.storageLayer().contains( - new Number640(unreachablePeer2.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = unreachablePeer1.get(unreachablePeer2.peerID()).routingConfiguration(r).sign() - .requestP2PConfiguration(rp).fastGet(false).start().awaitUninterruptibly(); - // TODO: try peers even if no data found with fastget - System.err.println(futureGet.failedReason()); - Assert.assertTrue(futureGet.isSuccess()); - - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - } - } - - @Test - public void testVeryFewPeers() throws Exception { - final Random rnd = new Random(42); - Peer master = null; - Peer unreachablePeer = null; - try { - Peer[] peers = UtilsNAT.createNodes(3, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - private Collection getNeighbors(Peer peer) { - if (peer == null) { - return Collections.emptyList(); - } - - Map handlers = peer.connectionBean().dispatcher().searchHandler(5); - for (Map.Entry entry : handlers.entrySet()) { - if (entry.getValue() instanceof BaseRelayServer) { - return ((BaseRelayServer) entry.getValue()).getPeerMap(); - } - } - return Collections.emptyList(); - } - -} diff --git a/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java b/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java deleted file mode 100644 index 0e22f881f..000000000 --- a/android/src/test/java/net/tomp2p/relay/android/UtilsNAT.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright 2012 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.relay.android; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.util.Random; - -import net.tomp2p.connection.Bindings; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.AutomaticFuture; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.rpc.RPC.Commands; - -/* - * This is a copy of TestRelay from tomp2p-nat. Maven does not allow to depend on test code from other modules: - * http://jira.codehaus.org/browse/MNG-3559 - */ - -public class UtilsNAT { - - public static PeerDHT[] createNodesDHT(int nrOfPeers, Random rnd, int port) throws Exception { - return createNodesDHT(nrOfPeers, rnd, port, null); - } - - public static PeerDHT[] createNodesDHT(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture) - throws Exception { - return createNodesDHT(nrOfPeers, rnd, port, automaticFuture, false); - } - - /** - * Creates peers for testing. The first peer (peer[0]) will be used as the master. This means that - * shutting down - * peer[0] will shut down all other peers - * - * @param nrOfPeers - * The number of peers to create including the master - * @param rnd - * The random object to create random peer IDs - * @param port - * The port where the master peer will listen to - * @return All the peers, with the master peer at position 0 -> peer[0] - * @throws Exception - * If the creation of nodes fail. - */ - public static PeerDHT[] createNodesDHT(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture, - boolean maintenance) throws Exception { - if (nrOfPeers < 1) { - throw new IllegalArgumentException("Cannot create less than 1 peer"); - } - Bindings bindings = new Bindings();// .addInterface("lo"); - PeerDHT[] peers = new PeerDHT[nrOfPeers]; - final Peer master; - if (automaticFuture != null) { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - master = new PeerBuilder(peerId).ports(port).enableMaintenance(maintenance).bindings(bindings).peerMap(peerMap) - .start().addAutomaticFuture(automaticFuture); - peers[0] = new PeerBuilderDHT(master).start(); - - } else { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - master = new PeerBuilder(peerId).enableMaintenance(maintenance).bindings(bindings).peerMap(peerMap).ports(port) - .start(); - peers[0] = new PeerBuilderDHT(master).start(); - } - - for (int i = 1; i < nrOfPeers; i++) { - if (automaticFuture != null) { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - Peer peer = new PeerBuilder(peerId).masterPeer(master).enableMaintenance(maintenance) - .enableMaintenance(maintenance).peerMap(peerMap).bindings(bindings).start() - .addAutomaticFuture(automaticFuture); - peers[i] = new PeerBuilderDHT(peer).start(); - } else { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId).peerNoVerification()); - Peer peer = new PeerBuilder(peerId).enableMaintenance(maintenance).bindings(bindings).peerMap(peerMap) - .masterPeer(master).start(); - peers[i] = new PeerBuilderDHT(peer).start(); - } - } - System.err.println("peers created."); - return peers; - } - - /** - * Perfect routing, where each neighbor has contacted each other. This means that for small number of - * peers, every - * peer knows every other peer. - * - * @param peers - * The peers taking part in the p2p network. - */ - public static void perfectRouting(PeerDHT... peers) { - for (int i = 0; i < peers.length; i++) { - for (int j = 0; j < peers.length; j++) - peers[i].peer().peerBean().peerMap().peerFound(peers[j].peer().peerAddress(), null, null, null); - } - System.err.println("perfect routing done."); - } - - public static Peer[] createNodes(int nrOfPeers, Random rnd, int port) throws Exception { - return createNodes(nrOfPeers, rnd, port, null); - } - - public static Peer[] createNodes(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture) throws Exception { - return createNodes(nrOfPeers, rnd, port, automaticFuture, false); - } - - /** - * Creates peers for testing. The first peer (peer[0]) will be used as the master. This means that - * shutting down - * peer[0] will shut down all other peers - * - * @param nrOfPeers - * The number of peers to create including the master - * @param rnd - * The random object to create random peer IDs - * @param port - * The port where the master peer will listen to - * @return All the peers, with the master peer at position 0 -> peer[0] - * @throws Exception - * If the creation of nodes fail. - */ - public static Peer[] createNodes(int nrOfPeers, Random rnd, int port, AutomaticFuture automaticFuture, - boolean maintenance) throws Exception { - if (nrOfPeers < 1) { - throw new IllegalArgumentException("Cannot create less than 1 peer"); - } - - Bindings bindings = new Bindings().addAddress(InetAddress.getLocalHost()); - // Bindings bindings = new Bindings().addInterface("lo0"); - Peer[] peers = new Peer[nrOfPeers]; - if (automaticFuture != null) { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - peers[0] = new PeerBuilder(peerId).ports(port).enableMaintenance(maintenance).bindings(bindings) - .peerMap(peerMap).start().addAutomaticFuture(automaticFuture); - } else { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - peers[0] = new PeerBuilder(peerId).enableMaintenance(maintenance).bindings(bindings).peerMap(peerMap) - .ports(port).start(); - } - - for (int i = 1; i < nrOfPeers; i++) { - if (automaticFuture != null) { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId)); - peers[i] = new PeerBuilder(peerId).masterPeer(peers[0]).enableMaintenance(maintenance) - .enableMaintenance(maintenance).peerMap(peerMap).bindings(bindings).start() - .addAutomaticFuture(automaticFuture); - } else { - Number160 peerId = new Number160(rnd); - PeerMap peerMap = new PeerMap(new PeerMapConfiguration(peerId).peerNoVerification()); - peers[i] = new PeerBuilder(peerId).enableMaintenance(maintenance).bindings(bindings).peerMap(peerMap) - .masterPeer(peers[0]).start(); - } - } - System.err.println("peers created."); - return peers; - } - - /** - * Perfect routing, where each neighbor has contacted each other. This means that for small number of - * peers, every - * peer knows every other peer. - * - * @param peers - * The peers taking part in the p2p network. - */ - public static void perfectRouting(Peer... peers) { - for (int i = 0; i < peers.length; i++) { - for (int j = 0; j < peers.length; j++) - peers[i].peerBean().peerMap().peerFound(peers[j].peerAddress(), null, null, null); - } - System.err.println("perfect routing done."); - } - - public static PeerAddress createAddress() throws UnknownHostException { - return createAddress(new Number160("0x5678"), "127.0.0.1", 8005, 8006, false, false); - } - - public static PeerAddress createRandomAddress() throws UnknownHostException { - Random rnd = new Random(); - return createAddress(new Number160(rnd), "127.0.0.1", rnd.nextInt(10000), rnd.nextInt(10000), rnd.nextBoolean(), - rnd.nextBoolean()); - } - - public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, - boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { - InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false,false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); - return n1; - } - - /** - * Creates a message with random content - */ - public static Message createRandomMessage() { - Random rnd = new Random(); - - Message message = new Message(); - message.command(Commands.values()[rnd.nextInt(Commands.values().length)].getNr()); - message.type(Type.values()[rnd.nextInt(Type.values().length)]); - message.recipientSocket(new InetSocketAddress(1234)); - message.recipient(new PeerAddress(new Number160(rnd), message.recipientSocket())); - message.senderSocket(new InetSocketAddress(5678)); - message.sender(new PeerAddress(new Number160(rnd), message.senderSocket())); - return message; - } - - public static boolean messagesEqual(Message m1, Message m2) { - return m1.messageId() == m2.messageId() - && m1.hasContent() == m2.hasContent() - && m1.type() == m2.type() - && m1.command() == m2.command() - && m1.sender().equals(m2.sender()) - && m1.recipient().equals(m2.recipient()) - && m1.sender().tcpPort() == m2.sender().tcpPort() - && m1.sender().udpPort() == m2.sender().udpPort() - && m1.recipient().tcpPort() == m2.recipient().tcpPort() - && m1.recipient().udpPort() == m2.recipient().udpPort(); - } -} diff --git a/android/src/test/resources/logback.xml b/android/src/test/resources/logback.xml deleted file mode 100644 index bac251cdb..000000000 --- a/android/src/test/resources/logback.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java b/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java index 7c8fea6ea..71dbc2331 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java @@ -6,14 +6,12 @@ import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; -import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; import net.tomp2p.rpc.ObjectDataReply; public class ExampleHoleP { @@ -54,7 +52,7 @@ public static void main(String[] args) throws Exception { shutdown(); } - private static void setUp(String[] args) throws IOException { + private static void setUp(String[] args) throws IOException, InterruptedException { if (args.length > 0) { if (args.length > 1) { try { @@ -84,7 +82,7 @@ private static void setUp(String[] args) throws IOException { System.err.println("Bootstrap and Relay Setup Done!"); } - public static Peer setUpRelayingWithNewPeer() throws IOException { + public static Peer setUpRelayingWithNewPeer() throws IOException, InterruptedException { // Bootstrap natpeer Peer unreachable = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORT + 1).start(); PeerAddress pa = unreachable.peerBean().serverPeerAddress(); @@ -97,8 +95,9 @@ public static Peer setUpRelayingWithNewPeer() throws IOException { // setup relay, check NATType, and specify number of holes and punches PeerNAT uNat = new PeerBuilderNAT(unreachable).holePNumberOfHolePunches(numberOfPunches).holePNumberOfHoles(numberOfHoles).start(); - FutureRelayNAT frn = uNat.startRelay(new TCPRelayClientConfig(), master.peerAddress()); - frn.awaitUninterruptibly(); + uNat.startRelay(master.peerAddress()); + //TODO: wait until a relay is added + Thread.sleep(5000); System.err.println("unreachable peer with PeerAddress = " + unreachable.peerAddress().toString() + " bootstrapped!"); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java b/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java index 8ac27d6e9..6a436205a 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java @@ -18,16 +18,17 @@ import java.net.InetAddress; import java.util.Random; +import net.tomp2p.connection.PeerConnection; +import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; -import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; +import net.tomp2p.relay.RelayCallback; public class ExampleNAT { private final static int PORT_SERVER = 4000; @@ -55,14 +56,53 @@ public static void main(String[] args) throws Exception { public static void startClientNAT(String ip) throws Exception { Random r = new Random(43L); Peer peer = new PeerBuilder(new Number160(r)).ports(PORT_CLIENT).behindFirewall().start(); - PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - PeerAddress pa = new PeerAddress(Number160.ZERO, InetAddress.getByName(ip), PORT_SERVER, PORT_SERVER); + final PeerNAT peerNAT = new PeerBuilderNAT(peer).relayCallback(new RelayCallback() { + + @Override + public void onRelayRemoved(PeerAddress relay, PeerConnection object) { + System.out.println("relay removed: "+relay); + } + + @Override + public void onRelayAdded(PeerAddress relay, PeerConnection object) { + System.out.println("relay added: "+relay); + } + + @Override + public void onNoMoreRelays(int activeRelays) { + System.out.println("could not find more relays: "+activeRelays); + } + + @Override + public void onFullRelays(int activeRelays) { + System.out.println("could find all relays: "+activeRelays); + } + + @Override + public void onFailure(Exception e) { + e.printStackTrace(); + } + + @Override + public void onShutdown() { + System.out.println("shutdown"); + } + }).start(); + final PeerAddress pa = new PeerAddress(Number160.ZERO, InetAddress.getByName(ip), PORT_SERVER, PORT_SERVER); - FutureDiscover fd = peer.discover().peerAddress(pa).start(); - FutureNAT fn = peerNAT.startSetupPortforwarding(fd); - FutureRelayNAT frn = peerNAT.startRelay(new TCPRelayClientConfig(), fd, fn); + final FutureDiscover fd = peer.discover().peerAddress(pa).start(); + final FutureNAT fn = peerNAT.portForwarding(fd); + fn.addListener(new BaseFutureAdapter() { + + @Override + public void operationComplete(FutureNAT future) throws Exception { + if(future.isFailed()) { + peerNAT.startRelay(fd.reporter()); + } + + } + }); - frn.awaitUninterruptibly(); if (fd.isSuccess()) { System.out.println("found that my outside address is " + fd.peerAddress()); } else { @@ -73,12 +113,8 @@ public static void startClientNAT(String ip) throws Exception { System.out.println("NAT success: " + fn.peerAddress()); } else { System.out.println("failed " + fn.failedReason()); - } - - if (frn.isSuccess()) { - System.out.println("FutureRelay success"); - } else { - System.out.println("failed " + frn.failedReason()); + //this is enough time to print out the status of the relay search + Thread.sleep(5000); } peer.shutdown(); diff --git a/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java b/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java index f0450a25f..94fe73aa1 100644 --- a/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java +++ b/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java @@ -28,8 +28,17 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelClientConfiguration; +import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.StandardProtocolFamily; import net.tomp2p.dht.FutureGet; import net.tomp2p.dht.FuturePut; @@ -39,13 +48,13 @@ import net.tomp2p.examples.utils.Repeat; import net.tomp2p.examples.utils.RepeatRule; import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.BaseFutureListener; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.nat.FutureNAT; -import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; @@ -54,18 +63,10 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; +import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; import net.tomp2p.storage.Data; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Test bootstrapping, DHT operations like put/get/add/remove and sendDirect in both LAN and WAN environment * Test scenarios in direct connection, auto port forwarding or relay mode. @@ -608,7 +609,7 @@ private Peer bootstrapWithPortForwarding(int clientPort) { PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); + FutureNAT futureNAT = peerNAT.portForwarding(futureDiscover); futureNAT.awaitUninterruptibly(); if (futureNAT.isSuccess()) { log.info("Automatic port forwarding is setup. Now we do a futureDiscover again. Address = " @@ -639,9 +640,9 @@ private Peer bootstrapWithPortForwarding(int clientPort) { } } - private Peer bootstrapInRelayMode(int clientPort) { + private Peer bootstrapInRelayMode(int clientPort) throws InterruptedException { Number160 peerId = new Number160(new Random(43L)); - Peer peer = null; + final Peer peer; try { peer = new PeerBuilder(peerId).bindings(getBindings()).behindFirewall().ports(clientPort).start(); } catch (IOException e) { @@ -650,33 +651,66 @@ private Peer bootstrapInRelayMode(int clientPort) { return null; } - PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); - FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT); - futureRelayNAT.awaitUninterruptibly(); - if (futureRelayNAT.isSuccess()) { - log.info("Bootstrap using relay was successful. Address = " + peer.peerAddress()); + final PeerNAT peerNAT = new PeerBuilderNAT(peer).relayCallback(new RelayCallback() { + + @Override + public void onRelayRemoved(PeerAddress relay, PeerConnection object) { + log.info("Relay was removed. Address = " + relay); + } + + @Override + public void onRelayAdded(PeerAddress relay, PeerConnection object) { + log.info("Bootstrap using relay was successful. Address = " + relay); + } + + @Override + public void onNoMoreRelays(int activeRelays) { + log.info("No more relays found. Active relays: " + activeRelays); + } + + @Override + public void onFullRelays(int activeRelays) { + log.info("All relays found. Active relays: " + activeRelays); + } + + @Override + public void onFailure(Exception e) { + log.error("error", e); + } - FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureBootstrap.awaitUninterruptibly(); - if (futureBootstrap.isSuccess()) { - return peer; - } else { - log.warn("Bootstrap failed. Reason = " + futureBootstrap.failedReason()); + @Override + public void onShutdown() { peer.shutdown().awaitUninterruptibly(); - return null; } + }).start(); + final FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); + FutureNAT futureNAT = peerNAT.portForwarding(futureDiscover); + + futureNAT.addListener(new BaseFutureAdapter() { + + @Override + public void operationComplete(FutureNAT future) throws Exception { + if(future.isFailed()) { + peerNAT.startRelay(futureDiscover.reporter()); + } + } + }); + + //make the return also a future + Thread.sleep(5000); + + FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); + futureBootstrap.awaitUninterruptibly(); + if (futureBootstrap.isSuccess()) { + return peer; } else { - log.error("Bootstrap using relay failed " + futureRelayNAT.failedReason()); - futureRelayNAT.shutdown(); - peer.shutdown().awaitUninterruptibly(); + log.warn("Bootstrap failed. Reason = " + futureBootstrap.failedReason()); + peer.shutdown(); return null; } - } - private Peer bootstrapInUnknownMode(int clientPort) { + private Peer bootstrapInUnknownMode(int clientPort) throws InterruptedException { resolvedConnectionType = ConnectionType.DIRECT; Peer peer = bootstrapDirectConnection(clientPort); if (peer != null) @@ -698,7 +732,7 @@ private Peer bootstrapInUnknownMode(int clientPort) { return peer; } - private PeerDHT getDHTPeer(int clientPort) { + private PeerDHT getDHTPeer(int clientPort) throws InterruptedException { Peer peer; if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { peer = bootstrapDirectConnection(clientPort); diff --git a/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java b/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java deleted file mode 100644 index 115155185..000000000 --- a/nat/src/main/java/net/tomp2p/nat/FutureRelayNAT.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.tomp2p.nat; - -import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.BaseFutureImpl; -import net.tomp2p.p2p.Shutdown; -import net.tomp2p.relay.buffer.BufferRequestListener; - -public class FutureRelayNAT extends BaseFutureImpl { - - private Shutdown shutdown; - private BufferRequestListener bufferRequestListener; - - public FutureRelayNAT() { - self(this); - } - - public void done(final Shutdown shutdown) { - synchronized (lock) { - if (!completedAndNotify()) { - return; - } - this.type = FutureType.OK; - this.shutdown = shutdown; - } - notifyListeners(); - } - - public void done() { - synchronized (lock) { - if (!completedAndNotify()) { - return; - } - this.type = FutureType.OK; - this.shutdown = new Shutdown() { - @Override - public BaseFuture shutdown() { - return FutureRelayNAT.this; - } - }; - } - notifyListeners(); - - } - - public Shutdown shutdown() { - synchronized (lock) { - return shutdown; - } - } - - - public FutureRelayNAT bufferRequestListener(BufferRequestListener bufferRequestListener) { - this.bufferRequestListener = bufferRequestListener; - return this; - } - - public BufferRequestListener bufferRequestListener() { - return bufferRequestListener; - } -} diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index 203abcdfb..9a3d238d3 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -1,7 +1,5 @@ package net.tomp2p.nat; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -22,12 +20,7 @@ import net.tomp2p.relay.DistributedRelay; import net.tomp2p.relay.RconRPC; import net.tomp2p.relay.RelayCallback; -import net.tomp2p.relay.RelayClientConfig; import net.tomp2p.relay.RelayRPC; -import net.tomp2p.relay.RelayServerConfig; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; -import net.tomp2p.relay.tcp.TCPRelayServerConfig; public class PeerBuilderNAT { @@ -44,10 +37,13 @@ public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} public void onFailure(Exception e) {} @Override - public void onFullRelays() {} + public void onFullRelays(int activeRelays) {} @Override - public void onNoMoreRelays() {} + public void onNoMoreRelays(int activeRelays) {} + + @Override + public void onShutdown() {} }; final private Peer peer; @@ -56,17 +52,12 @@ public void onNoMoreRelays() {} private Boolean relayMaintenance; - private RelayClientConfig relayConfig; - private RelayCallback relayCallback; private BootstrapBuilder bootstrapBuilder; private Integer peerMapUpdateIntervalSeconds; - // holds multiple implementations for serving relay peers - private Map relayServerConfigurations; - private static final int DEFAULT_NUMBER_OF_HOLEP_HOLES = 3; private int holePNumberOfHoles = DEFAULT_NUMBER_OF_HOLEP_HOLES; private static final int DEFAULT_NUMBER_OF_HOLE_PUNCHES = 3; @@ -76,10 +67,6 @@ public void onNoMoreRelays() {} public PeerBuilderNAT(Peer peer) { this.peer = peer; - - // add TCP server by default - this.relayServerConfigurations = new HashMap(); - relayServerConfigurations.put(RelayType.OPENTCP, new TCPRelayServerConfig()); } public boolean isManualPorts() { @@ -95,34 +82,6 @@ public PeerBuilderNAT manualPorts(boolean manualPorts) { return this; } - /** - * @return the relay server configurations. By default, - * {@link RelayType#OPENTCP} is implemented. - */ - public Map relayServerConfigurations() { - return relayServerConfigurations; - } - - /** - * Set all relay server configurations - * - * @return this instance - */ - public PeerBuilderNAT relayServerConfigurations(Map relayServerConfigurations) { - this.relayServerConfigurations = relayServerConfigurations; - return this; - } - - /** - * Add a new server configuration (e.g. for {@link RelayType#ANDROID}). - * - * @return this instance - */ - public PeerBuilderNAT addRelayServerConfiguration(RelayType relayType, RelayServerConfig configuration) { - relayServerConfigurations.put(relayType, configuration); - return this; - } - /** * This method specifies the amount of holes, which shall be punched by the * {@link HolePStrategy}. @@ -163,15 +122,6 @@ public int holePNumberOfPunches() { return holePNumberOfPunches; } - public RelayClientConfig relayConfig() { - return relayConfig; - } - - public PeerBuilderNAT relayConfig(RelayClientConfig relayConfig) { - this.relayConfig = relayConfig; - return this; - } - public RelayCallback relayCallback() { return relayCallback; } @@ -192,10 +142,6 @@ public PeerBuilderNAT executorService(ExecutorService executorService) { public PeerNAT start() { - if(relayConfig == null) { - relayConfig = new TCPRelayClientConfig(); - } - if(relayCallback == null) { relayCallback = DEFAULT_RELAY_CALLBACK; } @@ -220,21 +166,13 @@ public PeerNAT start() { peer.peerBean().holePNumberOfHoles(holePNumberOfHoles); peer.peerBean().holePNumberOfPunches(holePNumberOfPunches); - if (relayServerConfigurations == null) { - relayServerConfigurations = new HashMap(0); - } else { - // start the server configurations - for (RelayServerConfig config : relayServerConfigurations.values()) { - config.start(peer); - } - } final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC); if(executorService == null) { executorService = Executors.newSingleThreadExecutor(); } - DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, relayConfig, executorService, bootstrapBuilder); + DistributedRelay distributedRelay = new DistributedRelay(peer, relayRPC, executorService, bootstrapBuilder, relayCallback); peer.addShutdownListener(new Shutdown() { @Override @@ -244,6 +182,6 @@ public BaseFuture shutdown() { } }); - return new PeerNAT(peer, natUtils, relayRPC, manualPorts, distributedRelay, relayMaintenance, relayCallback, bootstrapBuilder, peerMapUpdateIntervalSeconds); + return new PeerNAT(peer, natUtils, relayRPC, manualPorts, distributedRelay, relayMaintenance, bootstrapBuilder, peerMapUpdateIntervalSeconds); } } diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index 70635e86a..9c2bd45b6 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -1,8 +1,13 @@ package net.tomp2p.nat; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Ports; import net.tomp2p.futures.BaseFuture; @@ -21,14 +26,10 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.relay.DistributedRelay; import net.tomp2p.relay.PeerMapUpdateTask; -import net.tomp2p.relay.RelayCallback; import net.tomp2p.relay.RelayRPC; import net.tomp2p.relay.RelayUtils; import net.tomp2p.rpc.RPC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class PeerNAT { private static final Logger LOG = LoggerFactory.getLogger(PeerNAT.class); @@ -38,20 +39,18 @@ public class PeerNAT { private final RelayRPC relayRPC; private final boolean manualPorts; private final DistributedRelay distributedRelay; - private final RelayCallback relayCallback; private boolean relayMaintenance; private BootstrapBuilder bootstrapBuilder; private int peerMapUpdateIntervalSeconds; PeerNAT(Peer peer, NATUtils natUtils, RelayRPC relayRPC, boolean manualPorts, DistributedRelay distributedRelay, - boolean relayMaintenance, RelayCallback relayCallback, BootstrapBuilder bootstrapBuilder, int peerMapUpdateIntervalSeconds) { + boolean relayMaintenance, BootstrapBuilder bootstrapBuilder, int peerMapUpdateIntervalSeconds) { this.peer = peer; this.natUtils = natUtils; this.relayRPC = relayRPC; this.manualPorts = manualPorts; this.distributedRelay = distributedRelay; this.relayMaintenance = relayMaintenance; - this.relayCallback = relayCallback; this.bootstrapBuilder = bootstrapBuilder; this.peerMapUpdateIntervalSeconds = peerMapUpdateIntervalSeconds; } @@ -199,8 +198,12 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { return null; } - public Shutdown startRelay() { - distributedRelay.setupRelays(relayCallback); + public Shutdown startRelay(PeerAddress... relays) { + return startRelay(Arrays.asList(relays)); + } + + public Shutdown startRelay(List relays) { + distributedRelay.setupRelays(relays); final Shutdown shutdownRelay = new Shutdown() { @Override diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 8ed89a508..ad8b6956a 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -47,9 +47,6 @@ public class DistributedRelay implements PeerMapChangeListener { //private final List relayClients; private final Set failedRelays; private final Map activeClients; - - //private final Collection relayListeners; - private final RelayClientConfig relayConfig; private FutureDone shutdownFuture = new FutureDone(); @@ -58,6 +55,8 @@ public class DistributedRelay implements PeerMapChangeListener { final private ExecutorService executorService; final private BootstrapBuilder bootstrapBuilder; + final private RelayCallback relayCallback; + private volatile List relays; /** @@ -73,21 +72,19 @@ public class DistributedRelay implements PeerMapChangeListener { * @param relayType * the kind of the relay connection */ - public DistributedRelay(final Peer peer, RelayRPC relayRPC, RelayClientConfig relayConfig, ExecutorService executorService, BootstrapBuilder bootstrapBuilder) { + public DistributedRelay(final Peer peer, RelayRPC relayRPC, ExecutorService executorService, BootstrapBuilder bootstrapBuilder, RelayCallback relayCallback) { this.peer = peer; this.relayRPC = relayRPC; - this.relayConfig = relayConfig; this.executorService = executorService; this.bootstrapBuilder = bootstrapBuilder; + this.relayCallback = relayCallback; activeClients = Collections.synchronizedMap(new HashMap()); - failedRelays = new ConcurrentCacheSet(relayConfig.failedRelayWaitTime()); + failedRelays = new ConcurrentCacheSet(60); peer.peerBean().peerMap().addPeerMapChangeListener(this); } - public RelayClientConfig relayConfig() { - return relayConfig; - } + /** * Returns connections to current relay peers @@ -119,6 +116,7 @@ public FutureDone shutdown() { synchronized (peer) { peer.notify(); } + relayCallback.onShutdown(); return shutdownFuture; } @@ -130,12 +128,13 @@ public FutureDone shutdown() { * * @return RelayFuture containing a {@link DistributedRelay} instance */ - public DistributedRelay setupRelays(final RelayCallback relayCallback) { + public DistributedRelay setupRelays(List relays) { + this.relays = relays; executorService.submit(new Runnable() { @Override public void run() { try { - startConnectionsLoop(relayCallback); + startConnectionsLoop(); } catch (Exception e) { relayCallback.onFailure(e); } @@ -146,7 +145,7 @@ public void run() { private List relayCandidates() { final List relayCandidates; - if (relayConfig.manualRelays().isEmpty()) { + if (!relays.isEmpty()) { // Get the neighbors of this peer that could possibly act as relays. Relay // candidates are neighboring peers that are not relayed themselves and have // not recently failed as relay or denied acting as relay. @@ -156,7 +155,9 @@ private List relayCandidates() { } else { // if the user sets manual relays, the failed relays are not removed, as this has to be done by // the user - relayCandidates = new ArrayList(relayConfig.manualRelays()); + synchronized (relays) { + relayCandidates = new ArrayList(relays); + } } //filterRelayCandidates @@ -187,7 +188,7 @@ private List relayCandidates() { */ - private void startConnectionsLoop(final RelayCallback relayCallback) throws InterruptedException { + private void startConnectionsLoop() throws InterruptedException { if(shutdown && activeClients.isEmpty()) { shutdownFuture.done(); @@ -199,10 +200,10 @@ private void startConnectionsLoop(final RelayCallback relayCallback) throws Inte return; } - if(activeClients.size() >= relayConfig.type().maxRelayCount()) { + if(activeClients.size() >= 5) { LOG.debug("we have enough relays"); allRelays = true; - relayCallback.onFullRelays(); + relayCallback.onFullRelays(activeClients.size()); updatePeerMap(); //wait at most x seconds for a restart of the loop executorService.submit(new Runnable() { @@ -212,7 +213,7 @@ public void run() { synchronized (peer) { peer.wait(60 * 1000); } - startConnectionsLoop(relayCallback); + startConnectionsLoop(); } catch (Exception e) { relayCallback.onFailure(e); } @@ -225,7 +226,7 @@ public void run() { final List relayCandidates = relayCandidates(); if(relayCandidates.isEmpty()) { LOG.debug("no more relays"); - relayCallback.onNoMoreRelays(); + relayCallback.onNoMoreRelays(activeClients.size()); updatePeerMap(); executorService.submit(new Runnable() { @Override @@ -234,7 +235,7 @@ public void run() { synchronized (peer) { peer.wait(60 * 1000); } - startConnectionsLoop(relayCallback); + startConnectionsLoop(); } catch (Exception e) { relayCallback.onFailure(e); } @@ -244,7 +245,7 @@ public void run() { } final PeerAddress candidate = relayCandidates.get(0); - final FutureDone futureDone = relayRPC.sendSetupMessage(candidate, relayConfig); + final FutureDone futureDone = relayRPC.sendSetupMessage(candidate); futureDone.addListener(new BaseFutureAdapter>() { @Override public void operationComplete(final FutureDone future) @@ -288,7 +289,7 @@ public void operationComplete(final FutureDone futureClose) relayCallback.onRelayRemoved(candidate, future.object()); } //loop again - startConnectionsLoop(relayCallback); + startConnectionsLoop(); } }); } @@ -307,7 +308,7 @@ private void updatePeerAddress() { socketAddresses = new ArrayList(activeClients.size()); //we can have more than the max relay count in our active client list. - int max = relayConfig.type().maxRelayCount(); + int max = 5; int i = 0; for (PeerAddress relay : activeClients.keySet()) { socketAddresses.add(new PeerSocketAddress(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); @@ -319,7 +320,7 @@ private void updatePeerAddress() { // update firewalled and isRelayed flags PeerAddress newAddress = peer.peerAddress().changeFirewalledTCP(!hasRelays).changeFirewalledUDP(!hasRelays) - .changeRelayed(hasRelays).changePeerSocketAddresses(socketAddresses).changeSlow(hasRelays && relayConfig.type().isSlow()); + .changeRelayed(hasRelays).changePeerSocketAddresses(socketAddresses).changeSlow(hasRelays); peer.peerBean().serverPeerAddress(newAddress); LOG.debug("Updated peer address {}, isrelay = {}", newAddress, hasRelays); } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 1d86aa085..678656e97 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -13,6 +13,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.netty.buffer.ByteBuf; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Responder; import net.tomp2p.futures.BaseFutureAdapter; @@ -39,13 +40,35 @@ public class Forwarder extends DispatchHandler { private final PeerConnection unreachablePeerConnection; private List> peerMap; + private final boolean isSlow; + + private final List buffer = Collections.synchronizedList(new ArrayList()); + + private int capacity = 16; + private long lastAccess = System.currentTimeMillis(); + private int bufferTimeSec = 60; - public Forwarder(Peer peer, PeerConnection unreachablePeerConnection) { + public Forwarder(Peer peer, PeerConnection unreachablePeerConnection, boolean isSlow) { super(peer.peerBean(), peer.connectionBean()); this.unreachablePeerConnection = unreachablePeerConnection; + this.isSlow = isSlow; + } + + private FutureDone forwardOrBuffer(final Message requestMessage) { + if(isSlow) { + final FutureDone futureDone = new FutureDone(); + Message fastReply = createResponseMessage(requestMessage, Type.PARTIALLY_OK); + addToBuffer(requestMessage); + return futureDone.done(fastReply); + + } else { + return forwardToUnreachable(requestMessage); + } } - public FutureDone forwardToUnreachable(final Message message) { + + + private FutureDone forwardToUnreachable(final Message message) { // Send message via direct message through the open connection to the unreachable peer LOG.debug("Sending {} to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); @@ -111,7 +134,7 @@ public void handleResponse(Message message, PeerConnection peerConnection, } else { messageCounter.incrementAndGet(); LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); - FutureDone response = forwardToUnreachable(message); + FutureDone response = forwardOrBuffer(message); response.addListener(new BaseFutureAdapter>() { @Override public void operationComplete(FutureDone future) throws Exception { @@ -225,4 +248,37 @@ public final void setPeerMap(List> peerMap, Messag Message preparedResponse) { this.peerMap = peerMap; } + + private void addToBuffer(Message requestMessage) { + buffer.add(requestMessage); + if(buffer.size() > 16 || lastAccess + (bufferTimeSec * 1000) < System.currentTimeMillis()) { + forwardMessages(buffer); + } + } + + private void forwardMessages(List buffer2) { + final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_4); + + // always keep the connection open + envelope.keepAlive(true); + ByteBuf bb = RelayUtils.composeMessageBuffer(buffered(), connectionBean().sender().channelClientConfiguration().signatureFactory()); + envelope.buffer(new Buffer(bb)); + + // this will be read RelayRPC.handlePiggyBackMessage + Collection peerSocketAddresses = new ArrayList(1); + peerSocketAddresses.add(new PeerSocketAddress(envelope.sender().inetAddress(), 0, 0)); + envelope.peerSocketAddresses(peerSocketAddresses); + + // Forward a message through the open peer connection to the unreachable peer. + RelayUtils.send(unreachablePeerConnection, peerBean(), connectionBean(), envelope); + } + + public List buffered() { + List retVal; + synchronized (buffer) { + retVal = new ArrayList(buffer); + } + buffer.clear(); + return retVal; + } } diff --git a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java index c79d927ee..2e26fb3d0 100644 --- a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java +++ b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java @@ -4,23 +4,16 @@ import java.util.Map; import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.message.NeighborSet; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerStatistic; -import net.tomp2p.relay.buffer.BufferedRelayClient; -import net.tomp2p.rpc.RPC; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The PeerMapUpdateTask is responsible for periodically sending the unreachable diff --git a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java index 944317d22..19ee82699 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayCallback.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayCallback.java @@ -11,8 +11,10 @@ public interface RelayCallback { void onFailure(Exception e); - void onFullRelays(); + void onFullRelays(int activeRelays); - void onNoMoreRelays(); + void onNoMoreRelays(int activeRelays); + + void onShutdown(); } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayClientConfig.java b/nat/src/main/java/net/tomp2p/relay/RelayClientConfig.java deleted file mode 100644 index 966e09b68..000000000 --- a/nat/src/main/java/net/tomp2p/relay/RelayClientConfig.java +++ /dev/null @@ -1,167 +0,0 @@ -package net.tomp2p.relay; - -import java.util.Collection; -import java.util.Collections; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; - -/** - * Holds multiple relay types with their configuration - * - * @author Nico Rutishauser - * - */ -public abstract class RelayClientConfig { - - private final RelayType type; - - // configurable - private int peerMapUpdateInterval; - private Collection manualRelays; - private int failedRelayWaitTime; - private int maxFail; - - protected RelayClientConfig(RelayType type, int peerMapUpdateInterval, int failedRelayWaitTime, int maxFail) { - this.type = type; - this.peerMapUpdateInterval = peerMapUpdateInterval; - this.failedRelayWaitTime = failedRelayWaitTime; - this.maxFail = maxFail; - - this.manualRelays = Collections.emptyList(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(type.toString()); - sb.append("[Interval:").append(peerMapUpdateInterval).append("s").append("]"); - return sb.toString(); - } - - /** - * @return the relay type - */ - public RelayType type() { - return type; - } - - /** - * Get the peer map update interval in seconds - */ - public int peerMapUpdateInterval() { - return peerMapUpdateInterval; - } - - /** - * Defines the time interval (in seconds) of sending the peer map of the unreachable peer - * to its relays. The routing requests are not relayed to the unreachable - * peer but handled by the relay peers. Therefore, the relay peers should - * always have an up-to-date peer map of the relayed peer - * - * @param peerMapUpdateInterval the interval of updating the own peer map at the relay - * @return this instance - */ - public RelayClientConfig peerMapUpdateInterval(int peerMapUpdateInterval) { - this.peerMapUpdateInterval = peerMapUpdateInterval; - return this; - } - - /** - * Add a relay to the relays list - */ - public void addManualRelay(PeerAddress manualRelay) { - synchronized (manualRelays) { - manualRelays.add(manualRelay); - } - } - - /** - * Set the relay list where the peer should connect to - * - * @param manualRelays publicly reachable relay nodes - * @return this instance - */ - public RelayClientConfig manualRelays(Collection manualRelays) { - if (manualRelays == null) { - this.manualRelays = Collections.emptySet(); - } else { - this.manualRelays = manualRelays; - } - return this; - } - - /** - * @return the currently configured list of relay peers - */ - public Collection manualRelays() { - return manualRelays; - } - - /** - * Defines how many seconds to wait at least until asking a relay that - * denied a relay request or a relay that failed to act as a relay again - * - * @param failedRelayWaitTime - * wait time in seconds - * @return this instance - */ - public RelayClientConfig failedRelayWaitTime(int failedRelayWaitTime) { - if (failedRelayWaitTime < 0) { - throw new IllegalArgumentException("Negative wait time is not allowed"); - } - this.failedRelayWaitTime = failedRelayWaitTime; - return this; - } - - /** - * @return How many seconds to wait at least until asking a relay that - * denied a relay request or a relay that failed to act as a relay - * again - */ - public int failedRelayWaitTime() { - return failedRelayWaitTime; - } - - /** - * Defines how many times a setup with a relay can fail before it's ignored - * - * @param maxFail the allowed number of fails - * @return this instance - */ - public RelayClientConfig maxFail(int maxFail) { - if (maxFail < 0) { - throw new IllegalArgumentException("Negative maximum fail count is not allowed"); - } - this.maxFail = maxFail; - return this; - } - - /** - * @return the maximum number of allowed fails - */ - public int maxFail() { - return maxFail; - } - - /** - * Creates a client object - */ - public abstract BaseRelayClient createClient(PeerConnection connection, Peer peer); - - /** - * Gives the opportunity to add more data to the setup message which is sent from the unreachable peer to - * the relay peer. - * - * @param message the message that is sent to the relay peer. - */ - public abstract void prepareSetupMessage(Message message); - - /** - * Gives the opportunity to add more data to the map update message. - * - * @param message the message which is regularly sent to the relay peer to update the routing table. - */ - public abstract void prepareMapUpdateMessage(Message message); -} diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 8bf2a5634..c2ea22482 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -1,16 +1,19 @@ package net.tomp2p.relay; +import java.io.IOException; import java.net.InetSocketAddress; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; import java.util.Collection; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.netty.buffer.ByteBuf; import net.tomp2p.connection.Dispatcher; import net.tomp2p.connection.PeerConnection; import net.tomp2p.connection.Responder; @@ -29,8 +32,6 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerStatistic; -import net.tomp2p.relay.buffer.BufferedRelayClient; -import net.tomp2p.relay.buffer.BufferedRelayServer; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; @@ -92,19 +93,13 @@ public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC) { register(RPC.Commands.RELAY.getNr()); } - public FutureDone sendSetupMessage(final PeerAddress candidate, final RelayClientConfig relayConfig) { + public FutureDone sendSetupMessage(final PeerAddress candidate) { final FutureDone futureDone = new FutureDone(); final Message message = createMessage(candidate, RPC.Commands.RELAY.getNr(), Type.REQUEST_1); // depend on the relay type whether to keep the connection open or close it after the setup. - message.keepAlive(relayConfig.type().keepConnectionOpen()); - - // encode the relay type in the message such that the relay node knows how to handle - message.intValue(relayConfig.type().ordinal()); - - // append relay-type specific data - //relayConfig.prepareSetupMessage(message); + message.keepAlive(true); LOG.debug("Setting up relay connection to peer {}, message {}", candidate, message); final FuturePeerConnection fpc = peer.createPeerConnection(candidate); @@ -170,15 +165,19 @@ public void handleResponse(final Message message, PeerConnection peerConnection, } else if (message.type() == Type.REQUEST_4 && message.command() == RPC.Commands.RELAY.getNr()) { // An unreachable peer requests the buffer at the relay peer // or a buffer is transmitted to the unreachable peer directly - //handleBuffer(message, responder); + handleBuffer(message, responder); } else if (message.type() == Type.REQUEST_5 && message.command() == RPC.Commands.RELAY.getNr()) { // A late response - //handleLateResponse(message, peerConnection, sign, responder); + handleLateResponse(message, peerConnection, sign, responder); } else { throw new IllegalArgumentException("Message content is wrong"); } } + + + + public Peer peer() { return this.peer; } @@ -250,7 +249,7 @@ private void handleSetup(Message message, final PeerConnection unreachablePeerCo // arrives) dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, this, command.getNr()); } else { - final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy); + final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow()); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, forwarder, command.getNr()); } } @@ -337,6 +336,11 @@ private void handleMap(Message message, Responder responder) { if (forwarder != null) { Collection map = message.neighborsSet(0).neighbors(); Message response = createResponseMessage(message, Type.OK); + List buffered = forwarder.buffered(); + if(buffered != null) { + ByteBuf bb = RelayUtils.composeMessageBuffer(buffered, peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); + response.buffer(new Buffer(bb)); + } forwarder.setPeerMap(RelayUtils.unflatten(map, message.sender()), message, response); responder.response(response); } else { @@ -344,110 +348,63 @@ private void handleMap(Message message, Responder responder) { responder.response(createResponseMessage(message, Type.NOT_FOUND)); } } - - /** - * There are two cases, when this method is called:
- *
    - *
  • The relay buffers messages for unreachable peers (like Android devices). They get notified when the - * buffer is full or request the buffer content by themselves through this request.
  • - *
  • The relay peer has buffered the messages and is able to transmit them through an already existing - * channel (e.g. in buffered tcp case). The unreachable peer can then process the buffer directly, without - * the need to obtain it at the relay peer.
  • - *
- * - * @param message - * @param responder - */ - /*private void handleBuffer(final Message message, final Responder responder) { - BaseRelayServer server = servers.get(message.sender().peerId()); - BaseRelayClient client = clients.get(message.sender().peerId()); - if (server != null && server instanceof BufferedRelayServer) { - LOG.debug("Handle buffer request from unreachable peer {} to server", message.sender()); - BufferedRelayServer bufferedServer = (BufferedRelayServer) server; - Message response = createResponseMessage(message, Type.OK); - - // add all buffered messages - Buffer bufferedMessages = bufferedServer.collectBufferedMessages(); - if (bufferedMessages != null) { - response.buffer(bufferedMessages); - } - - LOG.debug("Responding all buffered messages to Android device {}", message.sender()); - responder.response(response); - } else if (client != null && client instanceof BufferedRelayClient) { - LOG.debug("Handle message with buffer from server {} to unreachable client", message.sender()); - BufferedRelayClient bufferedClient = (BufferedRelayClient) client; - FutureDone futureDone = new FutureDone(); - bufferedClient.onReceiveMessageBuffer(message, futureDone); - futureDone.addListener(new BaseFutureAdapter>() { + + private void handleBuffer(final Message message, Responder responder) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { + //the unreachable peer gets the buffered messages + List buffered = RelayUtils.decomposeCompositeBuffer( + message.buffer(0).buffer(), message.recipient().createSocketTCP(), + message.sender().createSocketTCP(), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); + for(Message msg:buffered) { + DispatchHandler dh = connectionBean().dispatcher().associatedHandler(msg); + //TODO: add a custom responder and respond to the address found in the message + dh.forwardMessage(msg, null, new Responder() { + + @Override + public void responseFireAndForget() {} + + @Override + public FutureDone response(Message responseMessage) { + // this contains the real sender + Collection peerSocketAddresses = message.peerSocketAddresses(); + final InetSocketAddress sender; + if (!peerSocketAddresses.isEmpty()) { + sender = PeerSocketAddress.createSocketTCP(peerSocketAddresses.iterator().next()); + } else { + sender = new InetSocketAddress(0); + } + + responseMessage.recipient(responseMessage.recipient().changeAddress(sender.getAddress()).changePorts(sender.getPort(), sender.getPort())); + FutureResponse fr = RelayUtils.connectAndSend(peer(), responseMessage); + final FutureDone fd = new FutureDone(); + fr.addListener(new BaseFutureAdapter() { + + @Override + public void operationComplete(FutureResponse future) + throws Exception { + fd.done(); + } + }); + return fd; + } + @Override - public void operationComplete(FutureDone future) throws Exception { - // all buffered messages have been processed or at least started to process - responder.response(createResponseMessage(message, Type.OK)); + public void failed(Type type, String reason) { + LOG.error("could not sent to peer. {}", reason); } }); - } else { - responder.failed(Type.EXCEPTION, "This message type is intended for buffering forwarders only"); - } - }*/ - - /** - * There are two possibilites for this case: - *
    - *
  1. This peer did a request which was now finally answered by a slow peer.
  2. - *
  3. This is the relay peer of the requester which now receives the late response
  4. - *
- * - * @param message contains the (piggybacked) response - * @param responder - * @param peerConnection - * @param sign - */ - /*private void handleLateResponse(Message message, PeerConnection peerConnection, boolean sign, Responder responder) { - if (!message.sender().isSlow() || message.bufferList().isEmpty()) { - throw new IllegalArgumentException( - "Late response does not come from slow peer or does not contain the buffered message"); } - - Message realMessage = null; - try { - realMessage = RelayUtils.decodeRelayedMessage(message.buffer(0).buffer(), message.recipientSocket(), - message.senderSocket(), signatureFactory()); - } catch (Exception e) { - LOG.error("Cannot decode the late response", e); - responder.response(createResponseMessage(message, Type.EXCEPTION)); - return; - } - - LOG.debug("Received late response from slow peer: {}", realMessage); - // only the case when a unreachable peer makes a request to another slow, unreachable peer - Map pendingRequests = dispatcher().getPendingRequests(); - FutureResponse pendingRequest = pendingRequests.remove(realMessage.messageId()); - if (pendingRequest != null) { - // we waited for this response, answer it - pendingRequest.response(realMessage); - - // send ok, not fire and forget - style - LOG.debug("Successfully answered pending request {} with {}", pendingRequest.request(), realMessage); - responder.response(createResponseMessage(message, Type.OK, message.recipient())); - } else if (peer().peerAddress().isSlow()) { - // we're a slow peer but the pending request was not found. Don't send a reply, else we might end - // in a loop. Just trust in the timeout at the requester (might also be this peer). - LOG.error("No pending request found for message {}. Ignore it.", realMessage); + responder.response(createResponseMessage(message, Type.OK)); + } + + private void handleLateResponse(Message message, + PeerConnection peerConnection, boolean sign, Responder responder) { + FutureResponse fr = connectionBean().dispatcher().getPendingRequests().get(message.messageId()); + if(fr!=null) { + fr.response(message); + responder.response(createResponseMessage(message, Type.OK)); } else { - // handle Relayed <--> Relayed. - // This could be a pending message for one of the relayed peers, not for this peer - BaseRelayServer forwarder = servers.get(realMessage.recipient().peerId()); - if (forwarder == null) { - LOG.error("Forwarder for the relayed peer not found. Cannot send late response {}", realMessage); - responder.response(createResponseMessage(message, Type.NOT_FOUND)); - } else { - LOG.debug("We're just a relay peer. Send wrapped late response to requester wrapper: {} content: {}", - message, realMessage); - // because buffer is re-encoded when forwarding it to unreachable - message.restoreBuffers(); - forwarder.forwardToUnreachable(message); - } + responder.response(createResponseMessage(message, Type.NOT_FOUND)); } - }*/ + + } } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayServerConfig.java b/nat/src/main/java/net/tomp2p/relay/RelayServerConfig.java deleted file mode 100644 index 8c80595d5..000000000 --- a/nat/src/main/java/net/tomp2p/relay/RelayServerConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.tomp2p.relay; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.Responder; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.rpc.DispatchHandler; - -public abstract class RelayServerConfig { - - /** - * Called when the {@link PeerNAT} is started. - * @param peer the relay server peer - */ - public abstract void start(Peer peer); - - /** - * Helper method to create a response message - */ - protected Message createResponse(Message requestMessage, Type replyType, PeerAddress relayAddress) { - return DispatchHandler.createResponseMessage(requestMessage, replyType, relayAddress); - } - - /** - * Creates a new relay server for the unreachable peer that send the message. - * Note that the reply message must be sent by the implementation - * - * @return the server or null if something went wrong. - */ - public abstract BaseRelayServer createServer(Message message, final PeerConnection peerConnection, Responder responder, Peer peer); -} diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index dddfd0eb5..577b427e0 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -1,8 +1,5 @@ package net.tomp2p.relay; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; @@ -20,6 +17,11 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import net.tomp2p.connection.ConnectionBean; import net.tomp2p.connection.PeerBean; import net.tomp2p.connection.PeerConnection; @@ -39,12 +41,8 @@ import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; import net.tomp2p.peers.PeerStatistic; -import net.tomp2p.relay.buffer.MessageBuffer; import net.tomp2p.storage.AlternativeCompositeByteBuf; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class RelayUtils { private static final Logger LOG = LoggerFactory.getLogger(RelayUtils.class); diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/BufferRequestListener.java b/nat/src/main/java/net/tomp2p/relay/buffer/BufferRequestListener.java deleted file mode 100644 index 35aa62e29..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/BufferRequestListener.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.tomp2p.relay.buffer; - -import net.tomp2p.futures.FutureDone; - -public interface BufferRequestListener { - - /** - * Call this if the buffer should be obtained from a relay peer. - * - * @param relayPeerId the relay's peer id - */ - FutureDone sendBufferRequest(String relayPeerId); -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedMessageHandler.java b/nat/src/main/java/net/tomp2p/relay/buffer/BufferedMessageHandler.java deleted file mode 100644 index 29d20140f..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedMessageHandler.java +++ /dev/null @@ -1,133 +0,0 @@ -package net.tomp2p.relay.buffer; - -import java.util.List; - -import net.tomp2p.connection.Responder; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Buffer; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.rpc.DispatchHandler; -import net.tomp2p.rpc.RPC.Commands; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BufferedMessageHandler { - - private static final Logger LOG = LoggerFactory.getLogger(BufferedMessageHandler.class); - private final Peer peer; - - public BufferedMessageHandler(Peer peer) { - this.peer = peer; - } - - /** - * Takes the message containing the buffered messages. The buffer is decoded and the requests are executed - * - * @param bufferResponse the response of the relay peer - * @param futureDone done when all messages are passed to their handlers. Responses are not necessary sent - * before this future is done. - */ - public void handleBufferResponse(Message bufferResponse, FutureDone futureDone) { - Buffer buffer = bufferResponse.buffer(0); - if (buffer != null) { - // decompose the large buffer into a buffer for each message - List bufferedMessages = RelayUtils.decomposeCompositeBuffer(buffer.buffer(), bufferResponse.recipientSocket(), - bufferResponse.senderSocket(), peer.connectionBean().channelServer().channelServerConfiguration().signatureFactory()); - LOG.debug("Received {} buffered messages", bufferedMessages.size()); - - // process the messages - for (Message bufferedMessage : bufferedMessages) { - processMessage(bufferedMessage); - } - } else { - LOG.trace("Buffer message does not contain any buffered message"); - } - futureDone.done(); - } - - /** - * Execute the message by finding the dispatcher and the responding to the requester - * - * @param bufferedMessage the message of the requester to the unreachable peer that was buffered at the - * relay peer. - */ - private void processMessage(Message bufferedMessage) { - DispatchHandler handler = peer.connectionBean().dispatcher().associatedHandler(bufferedMessage); - if (handler == null) { - // ignore the message - LOG.error("Cannot find the associated handler to message {}", bufferedMessage); - return; - } - - try { - LOG.debug("Handle buffered message {}", bufferedMessage); - handler.handleResponse(bufferedMessage, null, false, new AndroidDirectResponder(bufferedMessage, handler)); - } catch (Exception e) { - LOG.error("Cannot handle the buffered message {}", bufferedMessage, e); - } - } - - /** - * Respond to the original requester (not the relay). - * - * @author Nico Rutishauser - * - */ - private class AndroidDirectResponder implements Responder { - - private final Message request; - private final DispatchHandler dispatchHandler; - - public AndroidDirectResponder(Message request, DispatchHandler dispatchHandler) { - this.request = request; - this.dispatchHandler = dispatchHandler; - } - - @Override - public FutureDone response(final Message responseMessage) { - final FutureDone futureDone = new FutureDone(); - // piggyback the late response. It will be unwrapped by the RelayRPC - Message envelope = dispatchHandler.createMessage(responseMessage.recipient(), Commands.RELAY.getNr(), Type.REQUEST_5); - try { - envelope.buffer(RelayUtils.encodeMessage(responseMessage, peer.connectionBean().channelServer().channelServerConfiguration().signatureFactory())); - } catch (Exception e) { - LOG.error("Cannot wrap the late response into an envelope", e); - return futureDone.failed("Cannot wrap the late response into an envelope"); - } - - LOG.debug("Sending late response {} in an envelope {}", responseMessage, envelope); - FutureResponse futureResponse = RelayUtils.connectAndSend(peer, envelope); - futureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if(future.isSuccess()) { - LOG.debug("Successfully sent late response to requester"); - futureDone.done(); - } else { - LOG.error("Late response could not be sent to requester. Reason: {}", future.failedReason()); - futureDone.failed("Late response could not be sent to requester."); - } - } - }); - return futureDone; - } - - @Override - public void failed(Type type, String reason) { - LOG.warn("Handling of buffered messages resulted in an error: {}", reason); - response(dispatchHandler.createResponseMessage(request, type)); - } - - @Override - public void responseFireAndForget() { - // respond through TCP anyway - response(dispatchHandler.createResponseMessage(request, Type.OK)); - } - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayClient.java b/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayClient.java deleted file mode 100644 index fb77ad108..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayClient.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.tomp2p.relay.buffer; - -import net.tomp2p.futures.FutureDone; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayClient; - -/** - * Extends the basic relay connection capabilities by functions to handle the buffer at the relay peer. - * This class is held at the unreachable peer (client side). - * - * @author Nico Rutishauser - * - */ -public abstract class BufferedRelayClient extends BaseRelayClient { - - private final BufferedMessageHandler bufferedMessageHandler; - protected final Peer peer; - - public BufferedRelayClient(PeerAddress relayAddress, Peer peer) { - super(relayAddress); - this.peer = peer; - this.bufferedMessageHandler = new BufferedMessageHandler(peer); - } - - public void onReceiveMessageBuffer(Message responseMessage, FutureDone futureDone) { - bufferedMessageHandler.handleBufferResponse(responseMessage, futureDone); - } - - /** - * Send a request to the relay peer to obtain the buffer. - */ - public abstract FutureDone sendBufferRequest(); -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayServer.java b/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayServer.java deleted file mode 100644 index 5c9dca9b9..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/BufferedRelayServer.java +++ /dev/null @@ -1,134 +0,0 @@ -package net.tomp2p.relay.buffer; - -import io.netty.buffer.ByteBuf; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.tomp2p.futures.FutureDone; -import net.tomp2p.message.Buffer; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.RelayUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class BufferedRelayServer extends BaseRelayServer implements MessageBufferListener { - - private static final Logger LOG = LoggerFactory.getLogger(BufferedRelayServer.class); - - private final MessageBuffer buffer; - private final MessageBufferConfiguration bufferConfig; - - // holds the messages that have already been released from the buffer (because any limit has been - // triggered or the buffer has been flushed) - private final List bufferedMessages; - - protected BufferedRelayServer(Peer peer, PeerAddress unreachablePeer, RelayType relayType, - MessageBufferConfiguration bufferConfig) { - super(peer, unreachablePeer, relayType); - this.bufferConfig = bufferConfig; - this.buffer = new MessageBuffer(bufferConfig); - this.bufferedMessages = Collections.synchronizedList(new ArrayList()); - - buffer.addListener(this); - } - - @Override - public FutureDone forwardToUnreachable(Message message) { - // create temporal OK message - final FutureDone futureDone = new FutureDone(); - final Message response = createResponseMessage(message, Type.PARTIALLY_OK); - response.recipient(message.sender()); - response.sender(unreachablePeerAddress()); - - try { - int messageSize = RelayUtils.getMessageSize(message, connectionBean().channelServer().channelServerConfiguration() - .signatureFactory()); - buffer.addMessage(message, messageSize); - } catch (Exception e) { - LOG.error("Cannot encode the message", e); - return futureDone.done(createResponseMessage(message, Type.EXCEPTION)); - } - - LOG.debug("Added message {} to buffer and returning a partially ok", message); - return futureDone.done(response); - } - - @Override - public void bufferFull(List messages) { - synchronized (bufferedMessages) { - bufferedMessages.addAll(messages); - } - - onBufferFull(); - } - - /** - * Called when the buffer is full and has been triggered. The messages in the buffer are kept in - * {@link BufferedRelayServer}. - */ - public abstract void onBufferFull(); - - @Override - public void bufferFlushed(List messages) { - synchronized (bufferedMessages) { - bufferedMessages.addAll(messages); - } - } - - /** - * Retrieves the messages that are ready to send. Ready to send means that they have been buffered and the - * Android device has already been notified. - * - * @return the buffer containing all buffered messages or null in case no message has been - * buffered - */ - public Buffer collectBufferedMessages() { - // flush the current buffer to get all messages - buffer.flushNow(); - - Buffer buffer = null;; - synchronized (bufferedMessages) { - if (bufferedMessages.isEmpty()) { - LOG.trace("Currently there are no buffered messages"); - } else { - ByteBuf byteBuffer = RelayUtils.composeMessageBuffer(bufferedMessages, connectionBean().channelServer() - .channelServerConfiguration().signatureFactory()); - LOG.debug("Buffer of {} messages collected", bufferedMessages.size()); - bufferedMessages.clear(); - buffer = new Buffer(byteBuffer); - } - } - - onBufferCollected(); - return buffer; - } - - /** - * Called when the buffer has been collected by the unreachable peer - */ - protected abstract void onBufferCollected(); - - @Override - protected void peerMapUpdated(Message originalMessage, Message preparedResponse) { - // Use the situation to send the buffer to the mobile phone - Buffer bufferedMessages = collectBufferedMessages(); - if (bufferedMessages != null) { - preparedResponse.buffer(bufferedMessages); - } - } - - /** - * Get the buffer configuration. Note, changing the configuraton does not affect the behavior. - */ - public MessageBufferConfiguration bufferConfiguration() { - return bufferConfig; - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBuffer.java b/nat/src/main/java/net/tomp2p/relay/buffer/MessageBuffer.java deleted file mode 100644 index 46022d582..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBuffer.java +++ /dev/null @@ -1,188 +0,0 @@ -package net.tomp2p.relay.buffer; - -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.SignatureException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Buffers messages for the unreachable peers. This class is thread-safe. - * If the buffer is full, the {@link MessageBufferListener}s are triggered. In the mean time, another list - * holds the previously buffered messages, until the buffer is collected. - * - * @author Nico Rutishauser - * - */ -public class MessageBuffer { - - private static final Logger LOG = LoggerFactory.getLogger(MessageBuffer.class); - private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); - - private final int messageCountLimit; - private final long bufferSizeLimit; - private final long bufferAgeLimitMS; - - private final AtomicLong bufferSize; - private final List> listeners; - - private final List buffer; - - private BufferAgeRunnable task; - - /** - * Create a new buffer using the configuration - * - * @param config the buffer limit configuration - */ - public MessageBuffer(MessageBufferConfiguration config) { - this(config.bufferCountLimit(), config.bufferSizeLimit(), config.bufferAgeLimit()); - } - - /** - * Create a new buffer with given limits - * - * @param bufferCountLimit the number of messages - * @param bufferSizeLimit the size of all messages (in bytes) - * @param bufferAgeLimitMS the maximum age of the oldest message - */ - public MessageBuffer(int bufferCountLimit, long bufferSizeLimit, long bufferAgeLimitMS) { - this.messageCountLimit = bufferCountLimit; - this.bufferSizeLimit = bufferSizeLimit; - this.bufferAgeLimitMS = bufferAgeLimitMS; - this.listeners = new ArrayList>(); - this.buffer = Collections.synchronizedList(new ArrayList()); - this.bufferSize = new AtomicLong(); - } - - public void addListener(MessageBufferListener listener) { - listeners.add(listener); - } - - /** - * Add an encoded message to the buffer - * - * @throws IOException - * @throws SignatureException - * @throws InvalidKeyException - */ - public void addMessage(T message, long messageSize) { - synchronized (buffer) { - if (buffer.isEmpty()) { - task = new BufferAgeRunnable(); - // schedule the task - worker.schedule(task, bufferAgeLimitMS, TimeUnit.MILLISECONDS); - } - - buffer.add(message); - } - - bufferSize.addAndGet(messageSize); - - LOG.debug("Added to the buffer: {}", message); - checkFull(); - } - - private void checkFull() { - boolean notify = false; - if (bufferSize.get() >= bufferSizeLimit) { - LOG.debug("The size of the buffer exceeds the limit of {} bytes", bufferSizeLimit); - notify = true; - } - - synchronized (buffer) { - if (buffer.size() >= messageCountLimit) { - LOG.debug("The number of messages exceeds the maximum message count of {}", messageCountLimit); - notify = true; - } - } - - if (notify) { - if (task != null) { - // cancel such that it does not notify the listener twice - task.cancel(); - } - notifyAndClear(true); - } - } - - /** - * Flush the buffer and notify the listeners - */ - public void flushNow() { - // no need to flush the buffer because it's empty - synchronized (buffer) { - if(buffer.isEmpty()) { - return; - } - } - - LOG.trace("Flushing buffer..."); - if (task != null) { - // cancel such that it does not notify the listener twice - task.cancel(); - } - notifyAndClear(false); - } - - /** - * Called when the buffer exceeds either the message count limit. the maximally - * allowed buffer size or the maximally allowed age of the first buffer entry. Otherwise - * false. - * - * @param wasFull true if this method was triggered because of buffer overflow. - * False if this method was triggered manually (because messages need to be ready now. - */ - private void notifyAndClear(boolean wasFull) { - List copy; - synchronized (buffer) { - if (buffer.isEmpty()) { - LOG.warn("Buffer is empty. Listener won't be notified."); - return; - } - - copy = new ArrayList(buffer); - buffer.clear(); - bufferSize.set(0); - } - - // notify the listeners with a copy of the buffer and the segmentation indices - for (MessageBufferListener listener : listeners) { - if(wasFull) { - listener.bufferFull(copy); - } else { - listener.bufferFlushed(copy); - } - } - } - - private class BufferAgeRunnable implements Runnable { - - private final AtomicBoolean cancelled; - - public BufferAgeRunnable() { - this.cancelled = new AtomicBoolean(false); - } - - @Override - public void run() { - if (!cancelled.get()) { - LOG.debug("Buffer age exceeds the limit of {}ms", bufferAgeLimitMS); - notifyAndClear(true); - } - } - - public void cancel() { - cancelled.set(true); - } - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferConfiguration.java b/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferConfiguration.java deleted file mode 100644 index 366b50db7..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferConfiguration.java +++ /dev/null @@ -1,118 +0,0 @@ -package net.tomp2p.relay.buffer; - -/** - * Configure multiple parameters of relay nodes being able to serve unreachable Android devices. This - * configuration need only to be set on the relay peer, not on the android device itself. - * - * @author Nico Rutishauser - * - */ -public class MessageBufferConfiguration { - - private int bufferCountLimit = 10; - private long bufferSizeLimit = Long.MAX_VALUE; - private long bufferAgeLimit = 5 * 60 * 1000; // 5 minutes - private int gcmSendRetries = 5; - - /** - * The maximum number of messages in the buffer. - * @return - */ - public int bufferCountLimit() { - return bufferCountLimit; - } - - /** - * Configures the maximal number of messages in the buffer. If the buffer is full, the device will be - * notified to download the messages. - * - * @param bufferCountLimit the maximal message count - */ - public MessageBufferConfiguration bufferCountLimit(int bufferCountLimit) { - this.bufferCountLimit = bufferCountLimit; - return this; - } - - /** - * The maximum size of the buffer content. - * @return - */ - public long bufferSizeLimit() { - return bufferSizeLimit; - } - - /** - * Configures the maximum size of the message buffer in bytes. If the buffer is full, the device will be - * notified to download the messages. - * - * @param bufferSizeLimit the maximal buffer size in bytes - */ - public MessageBufferConfiguration bufferSizeLimit(long bufferSizeLimit) { - this.bufferSizeLimit = bufferSizeLimit; - return this; - } - - /** - * The maximum age of the oldest object in the buffer in milliseconds - * @return - */ - public long bufferAgeLimit() { - return bufferAgeLimit; - } - - /** - * Configures the maximum age of the first message in the buffer. If the first message is put in at time 0 - * and the age is 60'000, the buffer will notify the device after 1 minute. - * - * @param bufferAgeLimit the maximum age of the content in the buffer in milliseconds - */ - public MessageBufferConfiguration bufferAgeLimit(long bufferAgeLimit) { - this.bufferAgeLimit = bufferAgeLimit; - return this; - } - - /** - * The number of retries to send the GCM message in case the Google Server fails. - * @return - */ - public int gcmSendRetries() { - return gcmSendRetries; - } - - /** - * The number of retries to send a message over GCM to the mobile device. - * - * @param gcmSendRetries the maximum number of attempts to try to reach the mobile device - */ - public MessageBufferConfiguration gcmSendRetries(int gcmSendRetries) { - this.gcmSendRetries = gcmSendRetries; - return this; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("MessageBuffer"); - - sb.append("[count="); - if(bufferCountLimit == Integer.MAX_VALUE) { - sb.append("inf"); - } else { - sb.append(bufferCountLimit); - } - - sb.append(", size="); - if(bufferSizeLimit == Long.MAX_VALUE) { - sb.append("inf"); - } else { - sb.append(bufferSizeLimit).append("b"); - } - - sb.append(", age="); - if(bufferAgeLimit == Long.MAX_VALUE) { - sb.append("inf]"); - } else { - sb.append(bufferAgeLimit).append("ms]"); - } - return sb.toString(); - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferListener.java b/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferListener.java deleted file mode 100644 index f45a40603..000000000 --- a/nat/src/main/java/net/tomp2p/relay/buffer/MessageBufferListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.tomp2p.relay.buffer; - -import java.util.List; - -public interface MessageBufferListener { - - /** - * Notification when the buffer at the relay peer is full. Use {@link MessageBuffer#collectBuffer()} to - * collect the messages - * - * @param messages the messages that were buffered. Note that the buffer of {@link MessageBuffer} is - * cleared as soon as this method call has been set. - */ - void bufferFull(List messages); - - /** - * Notification when the buffer at the relay peer has been flushed manually (using - * {@link MessageBuffer#flushNow()}. - * - * @param messages the messages that were buffered - */ - void bufferFlushed(List messages); -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClient.java b/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClient.java deleted file mode 100644 index 2b48f4dc0..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClient.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.tomp2p.relay.tcp; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.BaseRelayClient; -import net.tomp2p.relay.RelayUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TCPRelayClient extends BaseRelayClient { - - private final static Logger LOG = LoggerFactory.getLogger(TCPRelayClient.class); - - private final PeerConnection connection; - private final Peer peer; - - public TCPRelayClient(PeerConnection connection, Peer peer) { - super(connection.remotePeer()); - this.connection = connection; - this.peer = peer; - - initCloseListener(); - } - - private void initCloseListener() { - connection.closeFuture().addListener(new BaseFutureAdapter>() { - public void operationComplete(FutureDone future) throws Exception { - if (!peer.isShutdown()) { - // peer connection not open anymore -> remove and open a new relay connection - LOG.debug("Relay connection {} failed.", relayAddress()); - notifyCloseListeners(); - } - } - }); - } - - @Override - public FutureResponse sendToRelay(Message message) { - if(!connection.isOpen()) { - return new FutureResponse(message).failed("Connection to relay has been closed"); - } - message.keepAlive(true); - return RelayUtils.send(connection, peer.peerBean(), peer.connectionBean(), message); - } - - @Override - public FutureDone shutdown() { - return connection.closeFuture().done(); - } - - @Override - public void onMapUpdateFailed() { - // ignore because we already have a close listener on the TCP connection - } - - @Override - public void onMapUpdateSuccess() { - // success is nice, but we only care about failures - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClientConfig.java b/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClientConfig.java deleted file mode 100644 index d80c640a9..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayClientConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.tomp2p.relay.tcp; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.BaseRelayClient; -import net.tomp2p.relay.RelayClientConfig; -import net.tomp2p.relay.RelayType; - -public class TCPRelayClientConfig extends RelayClientConfig { - - /** - * Creates a TCP relay configuration - */ - public TCPRelayClientConfig() { - super(RelayType.OPENTCP, 15, 60, 2); - } - - @Override - public void prepareSetupMessage(Message message) { - // no need to add anything - } - - @Override - public void prepareMapUpdateMessage(Message message) { - // nothing to append - } - - @Override - public BaseRelayClient createClient(PeerConnection connection, Peer peer) { - return new TCPRelayClient(connection, peer); - } - -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServer.java b/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServer.java deleted file mode 100644 index aeedf9b44..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServer.java +++ /dev/null @@ -1,129 +0,0 @@ -package net.tomp2p.relay.tcp; - -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Buffer; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.rpc.RPC; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The RelayForwarder is responsible for forwarding all messages that are - * received on a relay peer, but are intended for an unreachable peer that is - * connected to the relay peer. Every unreachable node has an own instance of - * this class at the relay server. - * - * @author Raphael Voellmy - * @author Nico Rutishauser - * - */ -public class TCPRelayServer extends BaseRelayServer { - - private final static Logger LOG = LoggerFactory.getLogger(TCPRelayServer.class); - - // connection to unreachable peer - private final PeerConnection peerConnection; - - /** - * - * @param peerConnection - * A peer connection to an unreachable peer that is permanently - * open - * @param peer - * The relay peer - * @param config the connection configuration - */ - public TCPRelayServer(final PeerConnection peerConnection, final Peer peer) { - super(peer, peerConnection.remotePeer(), RelayType.OPENTCP); - this.peerConnection = peerConnection.changeRemotePeer(unreachablePeerAddress()); - - // add a listener when the connection is closed - peerConnection.closeFuture().addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureDone future) throws Exception { - notifyOfflineListeners(); - } - }); - - LOG.debug("Created TCP forwarder from peer {} to peer {}", peer.peerAddress(), unreachablePeerAddress()); - } - - @Override - public FutureDone forwardToUnreachable(final Message message) { - // Send message via direct message through the open connection to the unreachable peer - LOG.debug("Sending {} to unreachable peer {}", message, peerConnection.remotePeer()); - final Message envelope = createMessage(peerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); - try { - message.restoreContentReferences(); - // add the message into the payload - envelope.buffer(RelayUtils.encodeMessage(message, connectionBean().channelServer().channelServerConfiguration() - .signatureFactory())); - } catch (Exception e) { - LOG.error("Cannot encode the message", e); - return new FutureDone().failed(e); - } - - // always keep the connection open - envelope.keepAlive(true); - - // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress(message.sender().inetAddress(), 0, 0)); - envelope.peerSocketAddresses(peerSocketAddresses); - - // holds the message that will be returned to he requester - final FutureDone futureDone = new FutureDone(); - - // Forward a message through the open peer connection to the unreachable peer. - FutureResponse fr = RelayUtils.send(peerConnection, peerBean(), connectionBean(), envelope); - fr.addListener(new BaseFutureAdapter() { - public void operationComplete(FutureResponse future) throws Exception { - if (future.isSuccess()) { - InetSocketAddress senderSocket = message.recipientSocket(); - if (senderSocket == null) { - senderSocket = unreachablePeerAddress().createSocketTCP(); - } - InetSocketAddress recipientSocket = message.senderSocket(); - if (recipientSocket == null) { - recipientSocket = message.sender().createSocketTCP(); - } - - Buffer buffer = future.responseMessage().buffer(0); - Message responseFromUnreachablePeer = RelayUtils.decodeMessage(buffer.buffer(), recipientSocket, - senderSocket, connectionBean().channelServer().channelServerConfiguration().signatureFactory()); - responseFromUnreachablePeer.restoreContentReferences(); - futureDone.done(responseFromUnreachablePeer); - } else { - futureDone.failed("Could not forward message over TCP channel"); - } - } - }); - - return futureDone; - } - - @Override - protected void peerMapUpdated(Message originalMessage, Message preparedResponse) { - // ignore - } - - @Override - protected boolean isAlive() { - LOG.trace("peerconnection open? {}", peerConnection.isOpen()); - return peerConnection.isOpen(); - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServerConfig.java b/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServerConfig.java deleted file mode 100644 index 0caef8db5..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/TCPRelayServerConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.tomp2p.relay.tcp; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.Responder; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.RelayServerConfig; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TCPRelayServerConfig extends RelayServerConfig { - - private final static Logger LOG = LoggerFactory.getLogger(TCPRelayServerConfig.class); - - @Override - public void start(Peer peer) { - // nothing to do - } - - @Override - public BaseRelayServer createServer(Message message, PeerConnection peerConnection, Responder responder, Peer peer) { - if (peer.peerAddress().isRelayed()) { - // peer is behind a NAT as well -> deny request - LOG.warn("I cannot be a relay since I'm relayed as well! {}", message); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - - LOG.debug("Hello unreachable peer! You'll be relayed over an open TCP connection."); - TCPRelayServer tcpForwarder = new TCPRelayServer(peerConnection, peer); - responder.response(createResponse(message, Type.OK, peer.peerBean().serverPeerAddress())); - return tcpForwarder; - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClient.java b/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClient.java deleted file mode 100644 index b40d443f1..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClient.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.tomp2p.relay.tcp.buffered; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.RelayRPC; -import net.tomp2p.relay.buffer.BufferedRelayClient; -import net.tomp2p.relay.tcp.TCPRelayClient; - -/** - * Basically the same implementation as {@link TCPRelayClient}, but exending from the - * {@link BufferedRelayClient} such that the {@link RelayRPC} can distinguish between buffered and unbuffered - * connections. - * - * @author Nico Rutishauser - * - */ -public class BufferedTCPRelayClient extends BufferedRelayClient { - - private final TCPRelayClient tcpRelayClient; - - public BufferedTCPRelayClient(PeerConnection connection, Peer peer) { - super(connection.remotePeer(), peer); - tcpRelayClient = new TCPRelayClient(connection, peer); - } - - @Override - public FutureDone sendBufferRequest() { - // nothing to do because the buffer is sent automatically - return new FutureDone().done(); - } - - @Override - public FutureResponse sendToRelay(Message message) { - return tcpRelayClient.sendToRelay(message); - } - - @Override - public FutureDone shutdown() { - return tcpRelayClient.shutdown(); - } - - @Override - public void onMapUpdateSuccess() { - // nothing to do - } - - @Override - public void onMapUpdateFailed() { - // nothing to do - } - -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClientConfig.java b/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClientConfig.java deleted file mode 100644 index ee00320cd..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayClientConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -package net.tomp2p.relay.tcp.buffered; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.message.Message; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.BaseRelayClient; -import net.tomp2p.relay.RelayClientConfig; -import net.tomp2p.relay.RelayType; - -public class BufferedTCPRelayClientConfig extends RelayClientConfig { - - public BufferedTCPRelayClientConfig() { - super(RelayType.BUFFERED_OPENTCP, 15, 60, 2); - } - - @Override - public BaseRelayClient createClient(PeerConnection connection, Peer peer) { - return new BufferedTCPRelayClient(connection, peer); - } - - @Override - public void prepareSetupMessage(Message message) { - // nothing to attach - } - - @Override - public void prepareMapUpdateMessage(Message message) { - // nothing to attach - } - -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServer.java b/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServer.java deleted file mode 100644 index cc874c557..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServer.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.tomp2p.relay.tcp.buffered; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.message.Buffer; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.buffer.BufferedRelayServer; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; -import net.tomp2p.relay.tcp.TCPRelayServer; -import net.tomp2p.rpc.RPC.Commands; - -/** - * The buffered TCP server acts similar to the normal {@link TCPRelayServer}, but instead of sending messages - * immediately to the unreachable peer, messages are buffered for a certain time. - * - * @author Nico Rutishauser - * - */ -public class BufferedTCPRelayServer extends BufferedRelayServer { - - private final PeerConnection connection; - private final TCPRelayServer tcpRelayServer; - - protected BufferedTCPRelayServer(PeerConnection connection, Peer peer, MessageBufferConfiguration bufferConfig) { - super(peer, connection.remotePeer(), RelayType.BUFFERED_OPENTCP, bufferConfig); - this.connection = connection; - this.tcpRelayServer = new TCPRelayServer(connection, peer); - - // add a listener when the connection is closed - connection.closeFuture().addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureDone future) throws Exception { - notifyOfflineListeners(); - } - }); - } - - @Override - public void onBufferFull() { - Buffer messages = collectBufferedMessages(); - Message message = createMessage(connection.remotePeer(), Commands.RELAY.getNr(), Type.REQUEST_4); - message.buffer(messages); - - tcpRelayServer.forwardToUnreachable(message); - } - - @Override - protected void onBufferCollected() { - // ignore - } - - @Override - protected boolean isAlive() { - return connection.isOpen(); - } - -} diff --git a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServerConfig.java b/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServerConfig.java deleted file mode 100644 index d6d73cb05..000000000 --- a/nat/src/main/java/net/tomp2p/relay/tcp/buffered/BufferedTCPRelayServerConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.tomp2p.relay.tcp.buffered; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.Responder; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.relay.BaseRelayServer; -import net.tomp2p.relay.RelayServerConfig; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BufferedTCPRelayServerConfig extends RelayServerConfig { - - private final static Logger LOG = LoggerFactory.getLogger(BufferedTCPRelayServerConfig.class); - private final MessageBufferConfiguration bufferConfig; - - public BufferedTCPRelayServerConfig(MessageBufferConfiguration bufferConfig) { - this.bufferConfig = bufferConfig; - } - - @Override - public void start(Peer peer) { - // nothing to do - } - - @Override - public BaseRelayServer createServer(Message message, PeerConnection peerConnection, Responder responder, Peer peer) { - if (peer.peerAddress().isRelayed()) { - // peer is behind a NAT as well -> deny request - LOG.warn("I cannot be a relay since I'm relayed as well! {}", message); - responder.response(createResponse(message, Type.DENIED, peer.peerBean().serverPeerAddress())); - return null; - } - - LOG.debug("Hello unreachable peer! You'll be relayed over a buffered open TCP connection."); - BufferedTCPRelayServer tcpForwarder = new BufferedTCPRelayServer(peerConnection, peer, bufferConfig); - responder.response(createResponse(message, Type.OK, peer.peerBean().serverPeerAddress())); - return tcpForwarder; - } -} diff --git a/nat/src/test/java/net/tomp2p/holep/AbstractTestHoleP.java b/nat/src/test/java/net/tomp2p/holep/AbstractTestHoleP.java deleted file mode 100644 index ee69204a9..000000000 --- a/nat/src/test/java/net/tomp2p/holep/AbstractTestHoleP.java +++ /dev/null @@ -1,118 +0,0 @@ -package net.tomp2p.holep; - -import java.io.IOException; -import java.util.Random; - -import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.nat.FutureRelayNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.RelayType; -import net.tomp2p.relay.UtilsNAT; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; -import net.tomp2p.relay.tcp.TCPRelayServerConfig; -import net.tomp2p.rpc.ObjectDataReply; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; - -public class AbstractTestHoleP { - - protected Peer master; - protected Peer unreachable1; - protected Peer unreachable2; - - protected Peer[] peers = null; - protected static final Random RND = new Random(); - protected static final int PORTS = 4001; - protected static final int NUMBER_OF_NODES = 5; - protected static final int IDLE_UDP_SECONDS = 30; - - @Before - public void setupRelay() throws Exception { - // setup test peers - peers = UtilsNAT.createNodes(NUMBER_OF_NODES, RND, PORTS); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (int i = 0; i< peers.length; i++) { - if (i == 0) { - new PeerBuilderNAT(peers[i]).addRelayServerConfiguration(RelayType.OPENTCP, new TCPRelayServerConfig()).holePNumberOfHoles(8).start(); - } else { - new PeerBuilderNAT(peers[i]).start(); - } - } - - unreachable1 = setUpRelayingWithNewPeer(); - unreachable2 = setUpRelayingWithNewPeer(); - } - - public Peer setUpRelayingWithNewPeer() throws IOException { - // Test setting up relay peers - Peer unreachable = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORTS + 1).start(); - PeerAddress pa = unreachable.peerBean().serverPeerAddress(); - pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true); - unreachable.peerBean().serverPeerAddress(pa); - - // find neighbors - FutureBootstrap futureBootstrap = unreachable.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachable).start(); - FutureRelayNAT frn = uNat.startRelay(new TCPRelayClientConfig(), master.peerAddress()); - frn.awaitUninterruptibly(); - Assert.assertTrue(frn.isSuccess()); - - // Check if flags are set correctly - Assert.assertTrue(unreachable.peerAddress().isRelayed()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledTCP()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledUDP()); - - System.err.println("unreachable = " + unreachable.peerAddress()); - return unreachable; - } - - @After - public void shutdown() { - System.err.println("shutdown initiated!"); - for (Peer ele : peers) { - BaseFuture bf = ele.shutdown(); - bf.awaitUninterruptibly(); - } - BaseFuture bf1 = unreachable1.shutdown(); - bf1.awaitUninterruptibly(); - System.err.println("shutdown unreachable1 done!"); - - BaseFuture bf2 = unreachable2.shutdown(); - bf2.awaitUninterruptibly(); - System.err.println("shutdown unreachable 2 done!"); - } - - public void doTest() throws ClassNotFoundException, IOException { - final String requestString = "This is a test String"; - final String replyString = "SUCCESS HIT"; - - unreachable2.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - if (requestString.equals((String) request)) { - System.err.println("received: " + (String) request); - } - return replyString; - } - }); - - FutureDirect fd = unreachable1.sendDirect(unreachable2.peerAddress()).object(requestString).forceUDP(true).start(); - fd.awaitUninterruptibly(); - Assert.assertTrue(fd.isSuccess()); - Assert.assertEquals(replyString, (String) fd.object()); - } -} diff --git a/nat/src/test/java/net/tomp2p/holep/HolePStressTest.java b/nat/src/test/java/net/tomp2p/holep/HolePStressTest.java deleted file mode 100644 index c801ffbb7..000000000 --- a/nat/src/test/java/net/tomp2p/holep/HolePStressTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.tomp2p.holep; - -import static org.junit.Assert.*; - -import java.io.IOException; - -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.rpc.ObjectDataReply; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import ch.qos.logback.classic.Level; - -public class HolePStressTest extends AbstractTestHoleP { - - private static final Logger LOG = LoggerFactory.getLogger(HolePStressTest.class); - private static final int NUMBER_OF_MESSAGES = 1000; - - @Test - public void test() throws ClassNotFoundException, IOException { - // set Logger Level - ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) org.slf4j.LoggerFactory - .getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); - root.setLevel(Level.WARN); - LOG.warn("Logger with Level " + Level.WARN.toString() + " initialized"); - - for (int i=0; i bootstrapPeerAddresses = new ArrayList(); - bootstrapPeerAddresses.add(master.peerAddress()); - BootstrapBuilder builder = new BootstrapBuilder(unreachable).bootstrapTo(bootstrapPeerAddresses).ports(PORTS); - FutureBootstrap fBoot = builder.start(); - fBoot.awaitUninterruptibly(); - Assert.assertTrue(fBoot.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachable).start(); - FutureRelayNAT frn = uNat.startRelay(new TCPRelayClientConfig(), builder); - frn.awaitUninterruptibly(); - Assert.assertTrue(frn.isSuccess()); - - // Check if flags are set correctly - Assert.assertTrue(unreachable.peerAddress().isRelayed()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledTCP()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledUDP()); - - System.err.println("unreachable = " + unreachable.peerAddress()); - return unreachable; - } - -} diff --git a/nat/src/test/java/net/tomp2p/holep/IntegrationTestHolePuncher.java b/nat/src/test/java/net/tomp2p/holep/IntegrationTestHolePuncher.java deleted file mode 100644 index 3ef9b66d4..000000000 --- a/nat/src/test/java/net/tomp2p/holep/IntegrationTestHolePuncher.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.tomp2p.holep; - -import java.io.IOException; - -import org.junit.Test; - -public class IntegrationTestHolePuncher extends AbstractTestHoleP { - - @Test - public void testHolePunchPortPreserving() throws ClassNotFoundException, IOException { - System.err.println("PortPreserving() start!"); - doTest(); - } - - @Test - public void testRelayFallback() throws ClassNotFoundException, IOException { - ((HolePInitiatorImpl) unreachable1.peerBean().holePunchInitiator()).testCase(true); - System.err.println("testRelayFallback() start!"); - doTest(); - } -} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 2d13efd71..4d618595f 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -8,7 +8,6 @@ import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; import org.junit.After; import org.junit.Assert; @@ -385,11 +384,6 @@ private Peer createRelay(Number160 relayPeerId, int port) throws Exception { return relayPeer; } - private PeerNAT createRelay2(Number160 relayPeerId, int port) throws Exception { - Peer relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, port); - return new PeerBuilderNAT(relayPeer).start(); - } - private Peer createNattedPeer(final String ip, final int port, final int nr, final String retVal) throws UnknownHostException, IOException { Peer peer = LocalNATUtils.init(ip, port, nr); @@ -412,9 +406,11 @@ public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} @Override public void onFailure(Exception e) {e.printStackTrace();} @Override - public void onFullRelays() {} + public void onFullRelays(int activeRelays) {} @Override - public void onNoMoreRelays() {} + public void onNoMoreRelays(int activeRelays) {} + @Override + public void onShutdown() {} }; } private RelayCallback countDownRelayCallback2( @@ -433,9 +429,11 @@ public void onRelayAdded(PeerAddress candidate, PeerConnection object) { @Override public void onFailure(Exception e) {e.printStackTrace();} @Override - public void onFullRelays() {} + public void onFullRelays(int activeRelays) {} + @Override + public void onNoMoreRelays(int activeRelays) {} @Override - public void onNoMoreRelays() {} + public void onShutdown() {} }; } @@ -449,9 +447,11 @@ public void onRelayAdded(PeerAddress candidate, PeerConnection object) {} @Override public void onFailure(Exception e) {e.printStackTrace();} @Override - public void onFullRelays() {cl.countDown();} + public void onFullRelays(int activeRelays) {cl.countDown();} + @Override + public void onNoMoreRelays(int activeRelays) {} @Override - public void onNoMoreRelays() {} + public void onShutdown() {} }; } diff --git a/nat/src/test/java/net/tomp2p/relay/TestRcon.java b/nat/src/test/java/net/tomp2p/relay/TestRcon.java index 07660c15f..d8e6c7503 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRcon.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRcon.java @@ -4,27 +4,25 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDone; -import net.tomp2p.nat.FutureRelayNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; import net.tomp2p.rpc.ObjectDataReply; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - public class TestRcon { private Peer reachable = null; @@ -67,9 +65,8 @@ public void setupRelay() throws Exception { // setup relay PeerNAT uNat = new PeerBuilderNAT(unreachable).start(); - FutureRelayNAT frn = uNat.startRelay(new TCPRelayClientConfig(), master.peerAddress()); - frn.awaitUninterruptibly(); - Assert.assertTrue(frn.isSuccess()); + uNat.startRelay(master.peerAddress()); + Thread.sleep(5000); // Check if flags are set correctly Assert.assertTrue(unreachable.peerAddress().isRelayed()); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRelay.java b/nat/src/test/java/net/tomp2p/relay/TestRelay.java deleted file mode 100644 index c17ff4dc6..000000000 --- a/nat/src/test/java/net/tomp2p/relay/TestRelay.java +++ /dev/null @@ -1,855 +0,0 @@ -package net.tomp2p.relay; - -import java.net.InetAddress; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; - -import net.tomp2p.dht.FutureGet; -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.nat.FutureRelayNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.p2p.RequestP2PConfiguration; -import net.tomp2p.p2p.RoutingConfiguration; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number320; -import net.tomp2p.peers.Number640; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.relay.buffer.MessageBufferConfiguration; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; -import net.tomp2p.relay.tcp.TCPRelayServerConfig; -import net.tomp2p.relay.tcp.buffered.BufferedTCPRelayClientConfig; -import net.tomp2p.relay.tcp.buffered.BufferedTCPRelayServerConfig; -import net.tomp2p.rpc.DispatchHandler; -import net.tomp2p.rpc.ObjectDataReply; -import net.tomp2p.storage.Data; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class TestRelay { - - private static final Random rnd = new Random(42); - private final RelayType relayType; - private final RelayServerConfig serverConfig; - private final RelayClientConfig clientConfig; - - @SuppressWarnings("rawtypes") - @Parameterized.Parameters - public static Collection data() throws Exception { - MessageBufferConfiguration ageLimit = new MessageBufferConfiguration().bufferAgeLimit(2000).bufferCountLimit(Integer.MAX_VALUE).bufferSizeLimit(Long.MAX_VALUE); - MessageBufferConfiguration singleBuf = new MessageBufferConfiguration().bufferAgeLimit(Long.MAX_VALUE).bufferCountLimit(1).bufferSizeLimit(Long.MAX_VALUE); - - return Arrays.asList(new Object[][] { - { RelayType.OPENTCP, new TCPRelayServerConfig(), new TCPRelayClientConfig().peerMapUpdateInterval(5) }, - { RelayType.BUFFERED_OPENTCP, new BufferedTCPRelayServerConfig(ageLimit), new BufferedTCPRelayClientConfig().peerMapUpdateInterval(5) }, - { RelayType.BUFFERED_OPENTCP, new BufferedTCPRelayServerConfig(singleBuf), new BufferedTCPRelayClientConfig().peerMapUpdateInterval(5) } }); - } - - public TestRelay(RelayType relayType, RelayServerConfig serverConfig, RelayClientConfig clientConfig) { - this.relayType = relayType; - this.serverConfig = serverConfig; - this.clientConfig = clientConfig; - } - - private void waitMapUpdate() throws InterruptedException { - Thread.sleep(clientConfig.peerMapUpdateInterval() * 1000); - } - - @Test - public void testSetupRelayPeers() throws Exception { - final int nrOfNodes = 200; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(5000).start(); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - // Check if flags are set correctly - Assert.assertTrue(unreachablePeer.peerAddress().isRelayed()); - Assert.assertFalse(unreachablePeer.peerAddress().isFirewalledTCP()); - Assert.assertFalse(unreachablePeer.peerAddress().isFirewalledUDP()); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testBoostrap() throws Exception { - final int nrOfNodes = 10; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(5000).start(); - PeerAddress upa = unreachablePeer.peerBean().serverPeerAddress(); - upa = upa.changeFirewalledTCP(true).changeFirewalledUDP(true); - unreachablePeer.peerBean().serverPeerAddress(upa); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - // find neighbors again - futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - boolean otherPeersHaveRelay = false; - - for (Peer peer : peers) { - if (peer.peerBean().peerMap().allOverflow().contains(unreachablePeer.peerAddress())) { - for (PeerAddress pa : peer.peerBean().peerMap().allOverflow()) { - if (pa.peerId().equals(unreachablePeer.peerID())) { - if (pa.peerSocketAddresses().size() > 0) { - otherPeersHaveRelay = true; - } - System.err.println("-->" + pa.peerSocketAddresses()); - System.err.println("relay=" + pa.isRelayed()); - } - } - System.err.println("check 1! " + peer.peerAddress()); - } - - } - Assert.assertTrue(otherPeersHaveRelay); - - // wait for maintenance - waitMapUpdate(); - - boolean otherPeersMe = false; - for (Peer peer : peers) { - if (peer.peerBean().peerMap().all().contains(unreachablePeer.peerAddress())) { - System.err.println("check 2! " + peer.peerAddress()); - otherPeersMe = true; - } - } - Assert.assertTrue(otherPeersMe); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - /** - * Tests sending a message from an unreachable peer to another unreachable peer - */ - @Test - public void testRelaySendDirect() throws Exception { - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer1 = null; - Peer unreachablePeer2 = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1).start(); - FutureRelayNAT fbn = uNat1.startRelay(clientConfig, master.peerAddress()); - fbn.awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - System.out.print("Send direct message to unreachable peer " + unreachablePeer1.peerAddress()); - final String request = "Hello "; - final String response = "World!"; - - final AtomicBoolean test1 = new AtomicBoolean(false); - final AtomicBoolean test2 = new AtomicBoolean(false); - - // final Peer unr = unreachablePeer; - unreachablePeer1.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object obj) throws Exception { - test1.set(obj.equals(request)); - Assert.assertEquals(request.toString(), request); - test2.set(sender.inetAddress().toString().contains("0.0.0.0")); - System.err.println("Got sender:" + sender); - - // this is too late here, so we cannot test this here - // Collection list = new ArrayList(); - // list.add(new PeerSocketAddress(InetAddress.getByName("101.101.101.101"), 101, 101)); - // unr.peerBean().serverPeerAddress(unr.peerBean().serverPeerAddress().changePeerSocketAddresses(list)); - - return response; - } - }); - - unreachablePeer2 = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13338).start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2).start(); - fbn = uNat2.startRelay(clientConfig, peers[42].peerAddress()); - - fbn.awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // prevent rcon - Collection list = unreachablePeer2.peerBean().serverPeerAddress().peerSocketAddresses(); - if (list.size() >= clientConfig.type().maxRelayCount()) { - Iterator iterator = list.iterator(); - iterator.next(); - iterator.remove(); - } - list.add(new PeerSocketAddress(InetAddress.getByName("10.10.10.10"), 10, 10)); - unreachablePeer2.peerBean().serverPeerAddress( - unreachablePeer2.peerBean().serverPeerAddress().changePeerSocketAddresses(list)); - - System.err.println("unreachablePeer1: " + unreachablePeer1.peerAddress()); - System.err.println("unreachablePeer2: " + unreachablePeer2.peerAddress()); - - FutureDirect fd = unreachablePeer2.sendDirect(unreachablePeer1.peerAddress()).object(request).start() - .awaitUninterruptibly(); - System.err.println("got msg from: " + fd.responseMessage().sender()); - Assert.assertEquals(response, fd.object()); - // make sure we did not receive it from the unreachable peer with port 13337 - // System.err.println(fd.getWrappedFuture()); - // TODO: this case is true for relay - // Assert.assertEquals(fd.wrappedFuture().responseMessage().senderSocket().getPort(), 4001); - // TODO: this case is true for rcon - Assert.assertEquals(unreachablePeer1.peerID(), fd.responseMessage().sender().peerId()); - - Assert.assertTrue(test1.get()); - Assert.assertFalse(test2.get()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), fd.responseMessage().sender() - .peerSocketAddresses().size()); - } finally { - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - /** - * Tests sending a message from a reachable peer to an unreachable peer - */ - @Test - public void testRelaySendDirect2() throws Exception { - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // setup relay - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - System.out.print("Send direct message to unreachable peer"); - final String request = "Hello "; - final String response = "World!"; - - unreachablePeer.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object request) throws Exception { - Assert.assertEquals(request.toString(), request); - return response; - } - }); - - FutureDirect fd = peers[42].sendDirect(unreachablePeer.peerAddress()).object(request).start() - .awaitUninterruptibly(); - Assert.assertTrue(fd.isSuccess()); - Assert.assertEquals(response, fd.object()); - - // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(unreachablePeer.peerID(), fd.responseMessage().sender().peerId()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - /** - * Tests sending a message from an unreachable peer to a reachable peer - */ - @Test - public void testRelaySendDirect3() throws Exception { - final int nrOfNodes = 100; - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // setup relay - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(startRelay.isSuccess()); - - System.out.print("Send direct message from unreachable peer"); - final String request = "Hello "; - final String response = "World!"; - - Peer receiver = peers[42]; - receiver.objectDataReply(new ObjectDataReply() { - public Object reply(PeerAddress sender, Object request) throws Exception { - Assert.assertEquals(request.toString(), request); - return response; - } - }); - - FutureDirect fd = unreachablePeer.sendDirect(receiver.peerAddress()).object(request).start() - .awaitUninterruptibly(); - Assert.assertEquals(response, fd.object()); - - // make sure we did receive it from the unreachable peer with id - Assert.assertEquals(receiver.peerID(), fd.responseMessage().sender().peerId()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - @Test - public void testRelayRouting() throws Exception { - final int nrOfNodes = 8; // test only works if total nr of nodes is < 8 - Peer master = null; - Peer unreachablePeer = null; - try { - // setup test peers - Peer[] peers = UtilsNAT.createNodes(nrOfNodes, rnd, 4001); - master = peers[0]; - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerAddress upa = unreachablePeer.peerBean().serverPeerAddress(); - upa = upa.changeFirewalledTCP(true).changeFirewalledUDP(true); - unreachablePeer.peerBean().serverPeerAddress(upa); - - // find neighbors - FutureBootstrap futureBootstrap = unreachablePeer.bootstrap().peerAddress(peers[0].peerAddress()).start(); - futureBootstrap.awaitUninterruptibly(); - Assert.assertTrue(futureBootstrap.isSuccess()); - - // setup relay and lower the update interval to 5s - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT startRelay = uNat.startRelay(clientConfig, peers[0].peerAddress()); - FutureRelay frNAT = startRelay.awaitUninterruptibly().futureRelay(); - Assert.assertTrue(startRelay.isSuccess()); - - PeerAddress relayPeer = frNAT.relays().iterator().next().relayAddress(); - Peer found = null; - for (Peer p : peers) { - if (p.peerAddress().equals(relayPeer)) { - found = p; - break; - } - } - Assert.assertNotNull(found); - - // wait for at least one map update task (5s) - waitMapUpdate(); - - int nrOfNeighbors = getNeighbors(found).size(); - // we have in total 9 peers, we should find 8 as neighbors - Assert.assertEquals(8, nrOfNeighbors); - - System.err.println("neighbors: " + nrOfNeighbors); - for (BaseRelayClient relay : frNAT.relays()) { - System.err.println("pc:" + relay.relayAddress()); - } - - Assert.assertEquals(clientConfig.type().maxRelayCount(), frNAT.relays().size()); - - // Shut down a peer - peers[nrOfNodes - 1].shutdown().await(); - peers[nrOfNodes - 2].shutdown().await(); - peers[nrOfNodes - 3].shutdown().await(); - - /* - * needed because failure of a node is detected with periodic - * heartbeat and the routing table of the relay peers are also - * updated periodically - */ - waitMapUpdate(); - - Assert.assertEquals(nrOfNeighbors - 3, getNeighbors(found).size()); - Assert.assertEquals(clientConfig.type().maxRelayCount(), frNAT.relays().size()); - } finally { - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - if (master != null) { - master.shutdown().await(); - } - } - } - - @Test - public void testNoRelayDHT() throws Exception { - PeerDHT master = null; - PeerDHT slave = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - PeerMapConfiguration pmc = new PeerMapConfiguration(Number160.createHash(rnd.nextInt())); - slave = new PeerBuilderDHT(new PeerBuilder(Number160.ONE).peerMap(new PeerMap(pmc)).ports(13337).start()) - .start(); - printMapStatus(slave, peers); - FuturePut futurePut = peers[8].put(slave.peerID()).data(new Data("hello")).start().awaitUninterruptibly(); - futurePut.futureRequests().awaitUninterruptibly(); - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertFalse(slave.storageLayer().contains( - new Number640(slave.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (slave != null) { - slave.shutdown().await(); - } - } - } - - private void printMapStatus(PeerDHT slave, PeerDHT[] peers) { - for (PeerDHT peer : peers) { - if (peer.peerBean().peerMap().allOverflow().contains(slave.peerAddress())) { - System.err.println("found relayed peer in overflow bag " + peer.peerAddress()); - } - } - - for (PeerDHT peer : peers) { - if (peer.peerBean().peerMap().all().contains(slave.peerAddress())) { - System.err.println("found relayed peer in regular bag " + peer.peerAddress()); - } - } - } - - @Test - public void testRelayDHTSimple() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(1, rnd, 4000); - master = peers[0]; // the relay peer - new PeerBuilderNAT(master.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - uNat.startRelay(clientConfig, master.peerAddress()); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHT() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer, peers); - - FuturePut futurePut = peers[8].put(unreachablePeer.peerID()).data(new Data("hello")).start() - .awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - Assert.assertTrue(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGet() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - // bootstrap - unreachablePeer.peer().bootstrap().peerAddress(master.peerAddress()).start(); - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println("Unreachable: " + unreachablePeer.peerID()); - System.err.println("Relay: " + master.peerID()); - - FuturePut futurePut = peers[8].put(unreachablePeer.peerID()).data(new Data("hello")).routingConfiguration(r) - .requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = peers[8].get(unreachablePeer.peerID()).routingConfiguration(r).requestP2PConfiguration(rp) - .start().awaitUninterruptibly(); - Assert.assertTrue(futureGet.isSuccess()); - - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGet2() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer1 = null; - PeerDHT unreachablePeer2 = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1.peer()).start(); - FutureRelayNAT fbn1 = uNat1.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn1.isSuccess()); - - unreachablePeer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13338).start()) - .start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2.peer()).start(); - FutureRelayNAT fbn2 = uNat2.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn2.isSuccess()); - - peers[8] = unreachablePeer1; - peers[9] = unreachablePeer2; - UtilsNAT.perfectRouting(peers); - - // wait for relay setup - Thread.sleep(5000); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer1, peers); - printMapStatus(unreachablePeer2, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println(unreachablePeer1.peerID()); // f1 - System.err.println(unreachablePeer2.peerID()); // e7 - - FuturePut futurePut = unreachablePeer1.put(unreachablePeer2.peerID()).data(new Data("hello")) - .routingConfiguration(r).requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer2.storageLayer().contains( - new Number640(unreachablePeer2.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = unreachablePeer1.get(unreachablePeer2.peerID()).routingConfiguration(r) - .requestP2PConfiguration(rp).fastGet(false).start().awaitUninterruptibly(); - // TODO: try peers even if no data found with fastget - System.err.println(futureGet.failedReason()); - Assert.assertTrue(futureGet.isSuccess()); - - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - - System.err.println("DONE!"); - - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - } - } - - @Test - public void testRelayDHTPutGetSigned() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer1 = null; - PeerDHT unreachablePeer2 = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(10, rnd, 4000); - master = peers[0]; // the relay peer - - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); - KeyPair pair1 = gen.generateKeyPair(); - KeyPair pair2 = gen.generateKeyPair(); - - // Test setting up relay peers - unreachablePeer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).keyPair(pair1) - .ports(13337).start()).start(); - PeerNAT uNat1 = new PeerBuilderNAT(unreachablePeer1.peer()).start(); - FutureRelayNAT fbn1 = uNat1.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn1.isSuccess()); - - unreachablePeer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).keyPair(pair2) - .ports(13338).start()).start(); - PeerNAT uNat2 = new PeerBuilderNAT(unreachablePeer2.peer()).start(); - FutureRelayNAT fbn2 = uNat2.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn2.isSuccess()); - - peers[8] = unreachablePeer1; - peers[9] = unreachablePeer2; - UtilsNAT.perfectRouting(peers); - - // wait for relay setup - Thread.sleep(5000); - - // wait for maintenance to kick in - waitMapUpdate(); - - printMapStatus(unreachablePeer1, peers); - printMapStatus(unreachablePeer2, peers); - - RoutingConfiguration r = new RoutingConfiguration(5, 1, 1); - RequestP2PConfiguration rp = new RequestP2PConfiguration(1, 1, 0); - - System.err.println(unreachablePeer1.peerID()); // ..8bd - System.err.println(unreachablePeer2.peerID()); // ..af3 - - FuturePut futurePut = unreachablePeer1.put(unreachablePeer2.peerID()).data(new Data("hello")).sign() - .routingConfiguration(r).requestP2PConfiguration(rp).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - System.err.println(futurePut.failedReason()); - - Assert.assertTrue(futurePut.isSuccess()); - Assert.assertTrue(unreachablePeer2.storageLayer().contains( - new Number640(unreachablePeer2.peerID(), Number160.ZERO, Number160.ZERO, Number160.ZERO))); - - FutureGet futureGet = unreachablePeer1.get(unreachablePeer2.peerID()).routingConfiguration(r).sign() - .requestP2PConfiguration(rp).fastGet(false).start().awaitUninterruptibly(); - // TODO: try peers even if no data found with fastget - System.err.println(futureGet.failedReason()); - Assert.assertTrue(futureGet.isSuccess()); - - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - System.err.println("DONE!"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer1 != null) { - unreachablePeer1.shutdown().await(); - } - if (unreachablePeer2 != null) { - unreachablePeer2.shutdown().await(); - } - } - } - - @Test - public void testVeryFewPeers() throws Exception { - Peer master = null; - Peer unreachablePeer = null; - try { - Peer[] peers = UtilsNAT.createNodes(3, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (Peer peer : peers) { - new PeerBuilderNAT(peer).addRelayServerConfiguration(relayType, serverConfig).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer).start(); - FutureRelayNAT fbn = uNat.startRelay(clientConfig, master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } - - private Collection getNeighbors(Peer peer) { - if (peer == null) { - return Collections.emptyList(); - } - - Map handlers = peer.connectionBean().dispatcher().searchHandler(5); - for (Map.Entry entry : handlers.entrySet()) { - if (entry.getValue() instanceof BaseRelayServer) { - return ((BaseRelayServer) entry.getValue()).getPeerMap(); - } - } - return Collections.emptyList(); - } - -} diff --git a/nat/src/test/java/net/tomp2p/relay/TestRelayReplication.java b/nat/src/test/java/net/tomp2p/relay/TestRelayReplication.java deleted file mode 100644 index dcfb5f8ac..000000000 --- a/nat/src/test/java/net/tomp2p/relay/TestRelayReplication.java +++ /dev/null @@ -1,114 +0,0 @@ -package net.tomp2p.relay; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Random; - -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.nat.FutureRelayNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number640; -import net.tomp2p.relay.tcp.TCPRelayClientConfig; -import net.tomp2p.replication.IndirectReplication; -import net.tomp2p.storage.Data; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class TestRelayReplication { - - private static final Random rnd = new Random(42); - - private final int totalNumberPeers; - private final int replicationFactor; - - @SuppressWarnings("rawtypes") - @Parameterized.Parameters(name = "Peers: {0}, ReplicationFactor: {1}") - public static Collection data() throws Exception { - return Arrays.asList(new Object[][] { - { 3, 5 }, - { 3, 3 }, - { 10, 5}}); - } - - public TestRelayReplication(int totalNumberPeers, int replicationFactor) { - assert totalNumberPeers > 2; - this.totalNumberPeers = totalNumberPeers; - this.replicationFactor = replicationFactor; - } - - private void startReplication(int intervalMillis, boolean nRoot, PeerDHT... peers) { - for (PeerDHT peer : peers) { - IndirectReplication replication = new IndirectReplication(peer); - // set replication factor - replication.replicationFactor(replicationFactor); - // set replication frequency - replication.intervalMillis(intervalMillis); - // set kind of replication, default is 0Root - if (nRoot) { - replication.nRoot(); - } - // set flag to keep data, even when peer looses replication responsibility - replication.keepData(true); - // start the indirect replication - replication.start(); - } - } - - @Test - public void testRelayDHT() throws Exception { - PeerDHT master = null; - PeerDHT unreachablePeer = null; - try { - PeerDHT[] peers = UtilsNAT.createNodesDHT(totalNumberPeers - 1, rnd, 4000); - master = peers[0]; // the relay peer - UtilsNAT.perfectRouting(peers); - for (PeerDHT peer : peers) { - new PeerBuilderNAT(peer.peer()).start(); - } - - // Test setting up relay peers - unreachablePeer = new PeerBuilderDHT(new PeerBuilder(Number160.createHash(rnd.nextInt())).ports(13337).start()) - .start(); - PeerNAT uNat = new PeerBuilderNAT(unreachablePeer.peer()).start(); - - startReplication(300000, true, peers); - startReplication(300000, true, unreachablePeer); - - FutureRelayNAT fbn = uNat.startRelay(new TCPRelayClientConfig(), master.peerAddress()).awaitUninterruptibly(); - Assert.assertTrue(fbn.isSuccess()); - - Number160 contentKey = Number160.createHash(142); - Number160 domainKey = Number160.createHash(921); - - FuturePut futurePut = peers[0].put(unreachablePeer.peerID()).data(contentKey, new Data("hello"), Number160.ZERO).domainKey(domainKey).start().awaitUninterruptibly(); - // the relayed one is the slowest, so we need to wait for it! - futurePut.futureRequests().awaitUninterruptibly(); - Assert.assertTrue(futurePut.isSuccess()); - - // we cannot see the peer in futurePut.rawResult, as the relayed is the slowest and we finish - // earlier than that. - Assert.assertTrue(unreachablePeer.storageLayer().contains( - new Number640(unreachablePeer.peerID(), domainKey, contentKey, Number160.ZERO))); - - // Wait for the replication to calm down. Compare logs to see that many messages are sent forth and back over the relay peer - Thread.sleep(5000); - System.err.println("DONE"); - } finally { - if (master != null) { - master.shutdown().await(); - } - if (unreachablePeer != null) { - unreachablePeer.shutdown().await(); - } - } - } -} diff --git a/nat/src/test/java/net/tomp2p/relay/buffer/TestMessageBuffer.java b/nat/src/test/java/net/tomp2p/relay/buffer/TestMessageBuffer.java deleted file mode 100644 index 6ff2dad02..000000000 --- a/nat/src/test/java/net/tomp2p/relay/buffer/TestMessageBuffer.java +++ /dev/null @@ -1,205 +0,0 @@ -package net.tomp2p.relay.buffer; - -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.util.ArrayList; -import java.util.List; - -import net.tomp2p.connection.DSASignatureFactory; -import net.tomp2p.connection.SignatureFactory; -import net.tomp2p.message.Message; -import net.tomp2p.relay.RelayUtils; -import net.tomp2p.relay.UtilsNAT; - -import org.junit.Test; -// create three messages -// buffer did not trigger yet -// buffer triggered now -// create one message -// buffer triggered already -// create one message -// buffer did not trigger yet -// wait for the given time and slightly longer -// buffer triggered already -// wait again -// test that buffer did not trigger again -// create five messages -// buffer triggered by now, check the order -// create one message -// garbage collect -// create another message -// buffer triggered two messages -// instantly decompose since we don't need to send it here -public class TestMessageBuffer { - - private final SignatureFactory signature = new DSASignatureFactory(); - - @Test - public void testReachCountLimit() throws InvalidKeyException, SignatureException, IOException { - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(3, Long.MAX_VALUE, Long.MAX_VALUE); - buffer.addListener(listener); - - // create three messages - Message first = UtilsNAT.createRandomMessage(); - Message second = UtilsNAT.createRandomMessage(); - Message third = UtilsNAT.createRandomMessage(); - - - buffer.addMessage(first, RelayUtils.getMessageSize(first, signature)); - buffer.addMessage(second, RelayUtils.getMessageSize(second, signature)); - - // buffer did not trigger yet - assertEquals(0, listener.getTriggerCount()); - assertEquals(0, listener.getBuffer().size()); - - // buffer triggered now - buffer.addMessage(third, RelayUtils.getMessageSize(third, signature)); - assertEquals(1, listener.getTriggerCount()); - assertEquals(3, listener.getBuffer().size()); - } - - @Test - public void testReachSizeLimit() throws InvalidKeyException, SignatureException, IOException { - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(Integer.MAX_VALUE, 1, Long.MAX_VALUE); - buffer.addListener(listener); - - // create one message - buffer.addMessage(UtilsNAT.createRandomMessage(), 2); - - // buffer triggered already - assertEquals(1, listener.getTriggerCount()); - assertEquals(1, listener.getBuffer().size()); - } - - @Test - public void testReachAgeLimit() throws InvalidKeyException, SignatureException, IOException, InterruptedException { - long waitTime = 2000; - - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(Integer.MAX_VALUE, Long.MAX_VALUE, waitTime); - buffer.addListener(listener); - - // create one message - buffer.addMessage(UtilsNAT.createRandomMessage(), 10); - - // buffer did not trigger yet - assertEquals(0, listener.getTriggerCount()); - assertEquals(0, listener.getBuffer().size()); - - // wait for the given time and slightly longer - Thread.sleep((long) (waitTime * 1.5)); - - // buffer triggered already - assertEquals(1, listener.getTriggerCount()); - assertEquals(1, listener.getBuffer().size()); - - // wait again - Thread.sleep((long) (waitTime * 1.5)); - - // test that buffer did not trigger again - assertEquals(1, listener.getTriggerCount()); - assertEquals(1, listener.getBuffer().size()); - } - - @Test - public void testBufferFlush() throws InvalidKeyException, SignatureException, IOException, NoSuchAlgorithmException, InvalidKeySpecException { - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(3, Long.MAX_VALUE, Long.MAX_VALUE); - buffer.addListener(listener); - - // add two messages - buffer.addMessage(UtilsNAT.createRandomMessage(), 10); - buffer.addMessage(UtilsNAT.createRandomMessage(), 10); - - buffer.flushNow(); - - // check whether the buffer has been pre-emptied - assertEquals(1, listener.getTriggerCount()); - assertEquals(2, listener.getBuffer().size()); - } - - @Test - public void testBufferOrder() throws InvalidKeyException, SignatureException, IOException, NoSuchAlgorithmException, InvalidKeySpecException { - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(5, Long.MAX_VALUE, Long.MAX_VALUE); - buffer.addListener(listener); - - // create five messages - Message first = UtilsNAT.createRandomMessage(); - Message second = UtilsNAT.createRandomMessage(); - Message third = UtilsNAT.createRandomMessage(); - Message fourth = UtilsNAT.createRandomMessage(); - Message fifth = UtilsNAT.createRandomMessage(); - - buffer.addMessage(first, RelayUtils.getMessageSize(first, signature)); - buffer.addMessage(second, RelayUtils.getMessageSize(second, signature)); - buffer.addMessage(third, RelayUtils.getMessageSize(third, signature)); - buffer.addMessage(fourth, RelayUtils.getMessageSize(fourth, signature)); - buffer.addMessage(fifth, RelayUtils.getMessageSize(fifth, signature)); - - // buffer triggered by now, check the order - List content = listener.getBuffer(); - assertEquals(first.messageId(), content.get(0).messageId()); - assertEquals(second.messageId(),content.get(1).messageId()); - assertEquals(third.messageId(), content.get(2).messageId()); - assertEquals(fourth.messageId(), content.get(3).messageId()); - assertEquals(fifth.messageId(), content.get(4).messageId()); - } - - @Test - public void testGarbageCollect() throws InvalidKeyException, SignatureException, IOException, InterruptedException { - CountingBufferListener listener = new CountingBufferListener(); - MessageBuffer buffer = new MessageBuffer(2, Long.MAX_VALUE, Long.MAX_VALUE); - buffer.addListener(listener); - - // create one message - buffer.addMessage(UtilsNAT.createRandomMessage(), 10); - - // garbage collect - System.gc(); - - // create another message - buffer.addMessage(UtilsNAT.createRandomMessage(), 12); - - // buffer triggered two messages - assertEquals(2, listener.getBuffer().size()); - } - - private class CountingBufferListener implements MessageBufferListener { - - private final List buffer; - private int bufferFullTriggerCount; - - public CountingBufferListener() { - this.buffer = new ArrayList(); - this.bufferFullTriggerCount = 0; - } - - @Override - public void bufferFull(List messages) { - // instantly decompose since we don't need to send it here - this.buffer.addAll(messages); - bufferFullTriggerCount++; - } - - public int getTriggerCount() { - return bufferFullTriggerCount; - } - - public List getBuffer() { - return buffer; - } - - @Override - public void bufferFlushed(List messages) { - bufferFull(messages); - } - } -} diff --git a/pom.xml b/pom.xml index b1cc47385..01d7e78c8 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,6 @@ replication examples nat - android all storage dht From 751980b45b32784e3bb7c463923105827f0d9001 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 2 Aug 2015 18:22:47 +0200 Subject: [PATCH 058/135] removed 1.8 method --- nat/src/main/java/net/tomp2p/relay/DistributedRelay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index ad8b6956a..d36980835 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -284,7 +284,7 @@ public void operationComplete(final FutureDone futureClose) }); } else { LOG.debug("bad relay: {}", candidate); - activeClients.remove(candidate, future.object()); + activeClients.remove(candidate); updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); } From 052eaeaa28b02990fdbb45d299816f03bb8a2980 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 2 Aug 2015 18:32:08 +0200 Subject: [PATCH 059/135] remove 1.8 feature --- nat/src/main/java/net/tomp2p/relay/DistributedRelay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index d36980835..6c5621f84 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -267,7 +267,7 @@ public void operationComplete(final FutureDone futureClose) peer.peerBean().peerMap().peerFailed(candidate, new PeerException(AbortCause.SHUTDOWN, "remote open peer connection was closed")); failedRelays.add(future.object().remotePeer()); - activeClients.remove(candidate, future.object()); + activeClients.remove(candidate); updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); From 0cad9d1844c02721f17b00941ec4dc19af71e698 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 9 Aug 2015 23:13:41 +0200 Subject: [PATCH 060/135] work log: 13:45 - 15:30 / 16:45 - 17:00 / 21:30 - 23:00 - started with testing of forwarding peers. Tests revealed that the nat script was not enablig proxy arp, thus one NAT could not contact the other. This is now solved. - set as the sender address the real IP, not a wildcard address in order that the other peers sees our correct IP. However, we still see addresses that should not be there. This needs further investigation - don't update the peermap on second hand information, especially, when we see addresses that should not be there. --- .../net/tomp2p/connection/ChannelCreator.java | 14 +- .../net/tomp2p/connection/PeerCreator.java | 2 +- .../net/tomp2p/connection/Reservation.java | 13 +- .../java/net/tomp2p/connection/Sender.java | 2 +- .../main/java/net/tomp2p/peers/PeerMap.java | 11 +- .../java/net/tomp2p/rpc/DispatchHandler.java | 4 +- .../main/java/net/tomp2p/rpc/NeighborRPC.java | 1 + .../tomp2p/connection/TestReservation.java | 8 +- .../tomp2p/holep/manual/LocalNATUtils.java | 48 +++++- .../holep/manual/TestNATForwarding.java | 148 ++++++++++++++++++ .../net/tomp2p/holep/manual/TestNATRelay.java | 32 ++-- nat/src/test/resources/logback.xml | 8 +- nat/src/test/resources/nat-net.sh | 33 ++-- 13 files changed, 266 insertions(+), 58 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java diff --git a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java index 26683efab..2ea7f4bab 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java @@ -33,6 +33,7 @@ import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.GlobalEventExecutor; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Map; @@ -83,6 +84,8 @@ public class ChannelCreator { private final FutureDone futureChannelCreationDone; private final ChannelClientConfiguration channelClientConfiguration; + + private final InetAddress sendFromAddress; private EventExecutorGroup handlerExecutor; @@ -108,7 +111,7 @@ public class ChannelCreator { */ ChannelCreator(final EventLoopGroup workerGroup, final FutureDone futureChannelCreationDone, int maxPermitsUDP, int maxPermitsTCP, - final ChannelClientConfiguration channelClientConfiguration) { + final ChannelClientConfiguration channelClientConfiguration, InetAddress sendFromAddress) { this.workerGroup = workerGroup; this.futureChannelCreationDone = futureChannelCreationDone; this.maxPermitsUDP = maxPermitsUDP; @@ -116,6 +119,7 @@ public class ChannelCreator { this.semaphoreUPD = new Semaphore(maxPermitsUDP); this.semaphoreTCP = new Semaphore(maxPermitsTCP); this.channelClientConfiguration = channelClientConfiguration; + this.sendFromAddress = sendFromAddress; } /** @@ -154,7 +158,9 @@ public ChannelFuture createUDP(final boolean broadcast, final Map> channelHandlers2 = channelClientConfiguration.pipelineFilter().filter( channelHandlers, true, true); addHandlers(b, channelHandlers2); + + LOG.debug("Create TCP, use from address: {}", sendFromAddress); - ChannelFuture channelFuture = b.connect(socketAddress, new InetSocketAddress(channelClientConfiguration.senderTCP(), 0)); + ChannelFuture channelFuture = b.connect(socketAddress, new InetSocketAddress(sendFromAddress, 0)); recipients.add(channelFuture.channel()); setupCloseListener(channelFuture, semaphoreTCP, futureResponse); diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index cc5120c6d..57d103eef 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -100,7 +100,7 @@ public PeerCreator(final int p2pId, final Number160 peerId, final KeyPair keyPai //connection bean Sender sender = new Sender(peerId, peerBean.peerStatusListeners(), channelClientConfiguration, dispatcher, sendBehavior, peerBean); - Reservation reservation = new Reservation(workerGroup, channelClientConfiguration); + Reservation reservation = new Reservation(workerGroup, channelClientConfiguration, peerBean); connectionBean = new ConnectionBean(p2pId, dispatcher, sender, channelServer, reservation, channelClientConfiguration, timer); this.master = true; diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 6d50d3be5..e77e20507 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -18,6 +18,7 @@ import io.netty.channel.EventLoopGroup; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -37,6 +38,7 @@ import net.tomp2p.futures.FutureDone; import net.tomp2p.p2p.RequestConfiguration; import net.tomp2p.p2p.RoutingConfiguration; +import net.tomp2p.peers.PeerSocketAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,6 +67,7 @@ public class Reservation { // single thread private final ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, queue); private final EventLoopGroup workerGroup; + private final PeerBean peerBean; // we should be fair, otherwise we see connection timeouts due to unfairness // if busy @@ -89,7 +92,7 @@ public class Reservation { * TCP connections, maxPermitsPermanentTCP: the number of maximum * permanent TCP connections */ - public Reservation(final EventLoopGroup workerGroup, final ChannelClientConfiguration channelClientConfiguration) { + public Reservation(final EventLoopGroup workerGroup, final ChannelClientConfiguration channelClientConfiguration, final PeerBean peerBean) { this.workerGroup = workerGroup; this.maxPermitsUDP = channelClientConfiguration.maxPermitsUDP(); this.maxPermitsTCP = channelClientConfiguration.maxPermitsTCP(); @@ -98,6 +101,7 @@ public Reservation(final EventLoopGroup workerGroup, final ChannelClientConfigur this.semaphoreTCP = new Semaphore(maxPermitsTCP); this.semaphorePermanentTCP = new Semaphore(maxPermitsPermanentTCP); this.channelClientConfiguration = channelClientConfiguration; + this.peerBean = peerBean; } /** @@ -368,9 +372,12 @@ public void run() { futureChannelCreator.failed(e); return; } + + PeerSocketAddress psa = peerBean.serverPeerAddress().internalPeerSocketAddress(); + InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, permitsUDP, permitsTCP, - channelClientConfiguration); + channelClientConfiguration, fromAddress); addToSet(channelCreator); } finally { read.unlock(); @@ -435,7 +442,7 @@ public void run() { } channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, 0, permitsPermanentTCP, - channelClientConfiguration); + channelClientConfiguration, peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress()); addToSet(channelCreator); } finally { read.unlock(); diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 8583f6fce..bd3944f96 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -768,7 +768,7 @@ public void afterConnect(final FutureResponse futureResponse, final Message mess futureResponse.failed("could not create a " + (message.isUdp() ? "UDP" : "TCP") + " channel"); return; } - LOG.debug("about to connect to {} with channel {}, ff={}", message.recipient(), channelFuture.channel(), fireAndForget); + LOG.debug("about to connect to {} with channel {}, ff={}, msg={}", message.recipient(), channelFuture.channel(), fireAndForget, message); final Cancel connectCancel = createCancel(channelFuture); futureResponse.setCancel(connectCancel); channelFuture.addListener(new GenericFutureListener() { diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index 919d95ee6..203fc1681 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -868,14 +868,11 @@ public static PeerStatistic updateExistingVerifiedPeerAddress( final Map tmp, final PeerAddress peerAddress, final boolean firstHand, RTT roundTripTime) { synchronized (tmp) { PeerStatistic old = tmp.get(peerAddress.peerId()); - if (old != null) { - //TODO: this should only be from firsthand! - old.peerAddress(peerAddress); + if (old != null && firstHand) { + old.peerAddress(peerAddress); old.addRTT(roundTripTime); - if (firstHand) { - old.successfullyChecked(); - old.increaseNumberOfResponses(); - } + old.successfullyChecked(); + old.increaseNumberOfResponses(); return old; } } diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index fae1044cd..d4e6cee0c 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -156,7 +156,9 @@ public void forwardMessage(final Message requestMessage, PeerConnection peerConn //TODO: figure out how to include this. The only thing we currently missing are the ports if(requestMessage.sender().isNet4Private() || - (requestMessage.type() == Type.REQUEST_1 && requestMessage.command() == RPC.Commands.RELAY.getNr())) { + (requestMessage.type() == Type.REQUEST_1 && requestMessage.command() == RPC.Commands.RELAY.getNr()) || + (requestMessage.type() == Type.REQUEST_2 && requestMessage.command() == RPC.Commands.PING.getNr()) ) { + //request 2/ping is a ping discover, where we don't know our external address and port. Don't add this! LOG.debug("don't add the sender to the map (yet) {}", requestMessage); } else { peerBean.notifyPeerFound(requestMessage.sender(), requestMessage.sender(), peerConnection, null); diff --git a/core/src/main/java/net/tomp2p/rpc/NeighborRPC.java b/core/src/main/java/net/tomp2p/rpc/NeighborRPC.java index 159948bd9..6c469c7a3 100644 --- a/core/src/main/java/net/tomp2p/rpc/NeighborRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/NeighborRPC.java @@ -134,6 +134,7 @@ public FutureResponse closeNeighbors(final PeerAddress remotePeer, final SearchV message.bloomFilter(searchValues.contentBloomFilter()); } } + LOG.debug("Ask remote peer for neighbors with msg {}", message); return send(message, configuration, channelCreator); } diff --git a/core/src/test/java/net/tomp2p/connection/TestReservation.java b/core/src/test/java/net/tomp2p/connection/TestReservation.java index a5e3fd212..a728215de 100644 --- a/core/src/test/java/net/tomp2p/connection/TestReservation.java +++ b/core/src/test/java/net/tomp2p/connection/TestReservation.java @@ -125,7 +125,7 @@ public void testReservationTCP() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.maxPermitsTCP(tcpMax); c.pipelineFilter(new MyPipeLine()); - Reservation r = new Reservation(workerGroup, c); + Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); @@ -183,7 +183,7 @@ public void testReservationUDP() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsUDP(udpMax); - Reservation r = new Reservation(workerGroup, c); + Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(conn, 0); @@ -240,7 +240,7 @@ public void testReservationTCPNonCleanShutdown() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsTCP(tcpMax); - Reservation r = new Reservation(workerGroup, c); + Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); @@ -298,7 +298,7 @@ public void testReservationTCPNonCleanShutdown2() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsTCP(tcpMax); - Reservation r = new Reservation(ev, c); + Reservation r = new Reservation(ev, c, new PeerBean(null)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 3c57f9b40..95116cbed 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.NotSerializableException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; @@ -21,6 +22,7 @@ import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.rpc.ObjectDataReply; public class LocalNATUtils { private static final String TAG = "##BASE64##:"; @@ -187,7 +189,12 @@ public static Object fromString(String s) throws IOException, public static String toString(Serializable o) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(o); + try { + oos.writeObject(o); + } catch (NotSerializableException e) { + System.err.println("could not serialize object: " + o.getClass().getName()); + throw e; + } oos.close(); return Base64.getEncoder().encodeToString(baos.toByteArray()); } @@ -230,6 +237,20 @@ public static Peer init(String ip, int port, int peerId) return peer; } + public static Peer init(String ip, int port, int peerId, int forwardedPort) + throws UnknownHostException, IOException { + Bindings b = new Bindings(); + b.addAddress(InetAddress.getByName(ip)); + + ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); + + ccc.senderTCP(InetAddress.getByName(ip)); + Peer peer = new PeerBuilder(Number160.createHash(peerId)).portsExternal(forwardedPort).channelClientConfiguration(ccc).ports(port).bindings(b) + .start(); + System.out.println("Init "+peer.peerAddress()); + return peer; + } + public static Serializable shutdown(Peer... peers) { if(peers != null) { for(Peer peer: peers) { @@ -281,4 +302,29 @@ public void run() { } } } + + public static Peer createNattedPeer(final String ip, final int port, final int nr, final String retVal) + throws UnknownHostException, IOException { + Peer peer = LocalNATUtils.init(ip, port, nr); + peer.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return retVal; + } + }); + return peer; + } + + public static Peer createNattedPeer(final String ip, final int port, final int nr, int forwardedPort, final String retVal) + throws UnknownHostException, IOException { + Peer peer = LocalNATUtils.init(ip, port, nr, forwardedPort); + peer.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return retVal; + } + }); + return peer; + } + } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java new file mode 100644 index 000000000..e31a6f75f --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -0,0 +1,148 @@ +package net.tomp2p.holep.manual; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Random; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.FutureBootstrap; +import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; + +public class TestNATForwarding implements Serializable { + + final static private Random RND = new Random(42); + static private Number160 relayPeerId = new Number160(RND); + //### CHANGE THIS TO YOUR INTERFACE### + final static private String INF = "eth1"; + + @Before + public void before() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("start", "0", "sym"); + LocalNATUtils.executeNatSetup("start", "1", "sym"); + LocalNATUtils.executeNatSetup("forward", "0", "4000", "10.0.0.2", "5000"); + LocalNATUtils.executeNatSetup("forward", "1", "4000", "10.0.1.2", "5000"); + } + + @After + public void after() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("stop", "0"); + LocalNATUtils.executeNatSetup("stop", "1"); + } + + @Test + public void testForward() throws Exception { + Peer relayPeer = null; + + //System.exit(1); + + RemotePeer unr1 = null; + RemotePeer unr2 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); + + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerAddress relay = relayPeer.peerAddress(); + System.out.println("relay peer at: "+relay); + + //final Peer relayPeer1Copy = relayPeer1; + + unr1 = LocalNATUtils.executePeer(0, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, 4000, "peer1"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + Assert.assertTrue(fd1.isDiscoveredTCP()); + Thread.sleep(2000); + System.out.println("relay peer at1: "+relay); + BaseFuture fb = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + Thread.sleep(2000); + System.err.println(fb.failedReason()); + Assert.assertTrue(fb.isSuccess()); + return "done startup1"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + final Peer peer1 = (Peer) get("p1"); + + //discover the 2nd relay + //peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + //System.out.println("now we know peer realy2 "); + //final CountDownLatch cl2 = (CountDownLatch) get("cl2"); + //cl2.await(); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + //return "d"; + } + }); + + unr2 = LocalNATUtils.executePeer(1, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, 4000, "peer2"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + Assert.assertTrue(fd1.isDiscoveredTCP()); + Thread.sleep(2000); + System.out.println("relay peer at2: "+relay); + BaseFuture fb = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + Thread.sleep(2000); + Assert.assertTrue(fb.isSuccess()); + return "done startup1"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + final Peer peer1 = (Peer) get("p1"); + + //discover the 2nd relay + //peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); + //System.out.println("now we know peer realy2 "); + //final CountDownLatch cl2 = (CountDownLatch) get("cl2"); + //cl2.await(); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + //return "d"; + } + }); + + unr1.waitFor(); + unr2.waitFor(); + + Assert.assertEquals("done", unr1.getResult(1)); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 4d618595f..79f6e8e26 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -90,7 +90,7 @@ public void onFinished(int i) { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); @@ -187,7 +187,7 @@ public void onFinished(int i) { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); @@ -266,7 +266,7 @@ public void testFullRelay() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); FutureDiscover fd2 = peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); @@ -333,7 +333,7 @@ public void testLateRelay() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); //get to know both relays FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); @@ -384,18 +384,6 @@ private Peer createRelay(Number160 relayPeerId, int port) throws Exception { return relayPeer; } - private Peer createNattedPeer(final String ip, final int port, final int nr, final String retVal) - throws UnknownHostException, IOException { - Peer peer = LocalNATUtils.init(ip, port, nr); - peer.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - return retVal; - } - }); - return peer; - } - private RelayCallback countDownRelayCallback( final CountDownLatch cl) { return new RelayCallback() { @@ -470,7 +458,7 @@ public void testRealRelayDifferentNAT() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "me1"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "me1"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -511,7 +499,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.1.2", 5000, 1, "me2"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, "me2"); put("p1", peer1); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -569,10 +557,10 @@ public void testRealRelaySameNATNoRelay() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "n/a"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "n/a"); put("p1", peer1); - Peer peer2 = createNattedPeer("10.0.0.3", 5001, 1, "me"); + Peer peer2 = LocalNATUtils.createNattedPeer("10.0.0.3", 5001, 1, "me"); put("p2", peer2); @@ -622,10 +610,10 @@ public void testRealRelaySameNAT() throws Exception { @Override public Serializable execute() throws Exception { - Peer peer1 = createNattedPeer("10.0.0.2", 5000, 0, "n/a"); + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "n/a"); put("p1", peer1); - Peer peer2 = createNattedPeer("10.0.0.3", 5001, 1, "me"); + Peer peer2 = LocalNATUtils.createNattedPeer("10.0.0.3", 5001, 1, "me"); put("p2", peer2); peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index 809ce47fd..349bfcd3d 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -42,12 +42,18 @@ - --> + + + + + + + --> diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index fe51712c1..6b43ffc86 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -5,10 +5,10 @@ # using real hardware or virtual machines. The network setup looks as follows: # # ------------------------------------------------------------- -# +--------+ +------------+ -# global |DEV_REAL|--|NAT_REAL | -# namespace |your IP | |192.168.1.50| -# +--------+ +-----+------+ +# +--------+ +-------------+ +# global |DEV_REAL|--|NAT_REAL | +# namespace |your IP | |192.168.10.50| +# +--------+ +-----+-------+ # ----------------------------|-------------------------------- # +-----+----+ +--------+ # natX |NAT_WAN |--|NAT_LAN | @@ -44,8 +44,8 @@ # stop NAT # > nat-net.sh stop 0 # -# port forwarding, will forward the port in the natX namespace -# > nat-net.sh forward 0 4000 10.0.0.2 +# port forwarding, will forward the port in the natX namespace from port 4000 to port 5000 +# > nat-net.sh forward 0 4000 10.0.0.2 5000 # # start UPNP deamon in the natX namespace with the external interface NAT_WAN and internal interface NAT_LAN # > nat-net.sh upnp 0 @@ -68,8 +68,8 @@ # Author: Thomas Bocek # Set the IP address to something in your subnet of your global namespace -NAT_REAL="192.168.1.5$2" -NAT_REAL_NET="192.168.1.0" +NAT_REAL="192.168.10.5$2" +NAT_REAL_NET="192.168.10.0" # IP address should not be in a subnet of your global namespace, # as you would need an additional ARP proxy NAT_WAN="172.20.$2.1" @@ -107,13 +107,17 @@ start () { # loopback is important or getLocalHost() will hang for a long time! ip netns exec "unr$1" ifconfig "lo" 127.0.0.1 up + ip netns exec "nat$1" ifconfig "lo" 127.0.0.1 up + # add, modify routing - route del -net "$NAT_REAL_NET"/24 dev "nat$1_real" + #route del -net "$NAT_REAL_NET"/24 dev "nat$1_real" route add -net "$NAT_WAN_NET"/24 dev "nat$1_real" ip netns exec "unr$1" route add default gw "$NAT_LAN" ip netns exec "nat$1" route add default gw "$NAT_WAN" echo "routing set." + + echo 1 > "/proc/sys/net/ipv4/conf/nat$1_real/proxy_arp" # setup NAT ip netns exec "nat$1" echo 1 > /proc/sys/net/ipv4/ip_forward @@ -124,8 +128,9 @@ start () { ip netns exec "nat$1" iptables -t nat -A POSTROUTING -o "nat$1_wan" -j MASQUERADE --random fi - ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_wan" -o "nat$1_lan" -m state --state RELATED,ESTABLISHED -j ACCEPT - ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_lan" -o "nat$1_wan" -j ACCEPT + #if we have a drop policy, we need this accept rules + #ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_wan" -o "nat$1_lan" -m state --state RELATED,ESTABLISHED -j ACCEPT + #ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_lan" -o "nat$1_wan" -j ACCEPT echo "NAT setup $2". } @@ -138,8 +143,8 @@ stop () { } forward () { - ip netns exec "nat$1" iptables -t nat -A PREROUTING -i nat$1_wan -p tcp --dport $2 -j DNAT --to-destination $3:$2 - ip netns exec "nat$1" iptables -t nat -A PREROUTING -i nat$1_wan -p udp --dport $2 -j DNAT --to-destination $3:$2 + ip netns exec "nat$1" iptables -t nat -A PREROUTING -i nat$1_wan -p tcp --dport $2 -j DNAT --to-destination $3:$4 + ip netns exec "nat$1" iptables -t nat -A PREROUTING -i nat$1_wan -p udp --dport $2 -j DNAT --to-destination $3:$4 ip netns exec "nat$1" iptables -A FORWARD -d $3 -p tcp --dport $2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT ip netns exec "nat$1" iptables -A FORWARD -d $3 -p udp --dport $2 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT } @@ -167,7 +172,7 @@ case "$1" in ;; forward) - forward $2 $3 $4 + forward $2 $3 $4 $5 ;; upnp) From 6af3097349c576a50e17a50cfebd96c92b7f9641 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 9 Aug 2015 23:47:20 +0200 Subject: [PATCH 061/135] fixed null pointer in reservation --- core/src/main/java/net/tomp2p/connection/Reservation.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index e77e20507..214dc2ce2 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -440,9 +440,12 @@ public void run() { futureChannelCreator.failed(e); return; } + + PeerSocketAddress psa = peerBean.serverPeerAddress().internalPeerSocketAddress(); + InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, 0, permitsPermanentTCP, - channelClientConfiguration, peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress()); + channelClientConfiguration, fromAddress); addToSet(channelCreator); } finally { read.unlock(); From a8c5a95531c7ec0fa9b592da9cdd237b56f1b1cc Mon Sep 17 00:00:00 2001 From: tbocek Date: Mon, 10 Aug 2015 21:55:35 +0200 Subject: [PATCH 062/135] fix notification of peerinserted --- .../main/java/net/tomp2p/p2p/PeerBuilder.java | 2 +- .../main/java/net/tomp2p/peers/PeerMap.java | 20 +++++++++++++------ .../tomp2p/connection/TestReservation.java | 8 ++++---- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index c330ef83d..9f686bfe7 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -90,7 +90,7 @@ public String getAlgorithm() { } }; - private static final KeyPair EMPTY_KEY_PAIR = new KeyPair(EMPTY_PUBLIC_KEY, null); + public static final KeyPair EMPTY_KEY_PAIR = new KeyPair(EMPTY_PUBLIC_KEY, null); // if the permits are chosen too high, then we might run into timeouts as we // cant handle that many connections // withing the time limit diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index 203fc1681..ad9dbc7df 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -33,6 +33,7 @@ import net.tomp2p.p2p.PeerStatisticComparator; import net.tomp2p.utils.CacheMap; import net.tomp2p.utils.ConcurrentCacheMap; +import net.tomp2p.utils.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -322,14 +323,18 @@ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referre final int classMember = classMember(remotePeer.peerId()); // Update existing PeerStatistic with RTT info and potential new port - final PeerStatistic oldPeerStatistic = updateExistingVerifiedPeerAddress( + final Pair old = updateExistingVerifiedPeerAddress( peerMapVerified.get(classMember), remotePeer, firstHand, roundTripTime); - if (oldPeerStatistic != null) { + if (old != null && old.element1()) { // we update the peer, so we can exit here and report that we have // updated it. - notifyUpdate(remotePeer, oldPeerStatistic); + notifyUpdate(remotePeer, old.element0()); return true; - } else { + } else if (old != null && !old.element1()) { + //don't update, as we have second hand information that is not reliabel, we arleady have it, don't update + return false; + } + else { if (firstHand || (secondHand && !peerVerification)) { final Map map = peerMapVerified.get(classMember); boolean insterted = false; @@ -864,7 +869,7 @@ private static boolean updatePeerStatistic(final PeerAddress remotePeer, * @param roundTripTime * @return The old peer address if we have updated the peer, null otherwise */ - public static PeerStatistic updateExistingVerifiedPeerAddress( + public static Pair updateExistingVerifiedPeerAddress( final Map tmp, final PeerAddress peerAddress, final boolean firstHand, RTT roundTripTime) { synchronized (tmp) { PeerStatistic old = tmp.get(peerAddress.peerId()); @@ -873,7 +878,10 @@ public static PeerStatistic updateExistingVerifiedPeerAddress( old.addRTT(roundTripTime); old.successfullyChecked(); old.increaseNumberOfResponses(); - return old; + return new Pair(old, true); + } else if (old != null) { + //this is second hand information, don't update, as we already have it. + return new Pair(old, false); } } return null; diff --git a/core/src/test/java/net/tomp2p/connection/TestReservation.java b/core/src/test/java/net/tomp2p/connection/TestReservation.java index a728215de..719cd80a7 100644 --- a/core/src/test/java/net/tomp2p/connection/TestReservation.java +++ b/core/src/test/java/net/tomp2p/connection/TestReservation.java @@ -125,7 +125,7 @@ public void testReservationTCP() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.maxPermitsTCP(tcpMax); c.pipelineFilter(new MyPipeLine()); - Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); + Reservation r = new Reservation(workerGroup, c, new PeerBean(PeerBuilder.EMPTY_KEY_PAIR)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); @@ -183,7 +183,7 @@ public void testReservationUDP() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsUDP(udpMax); - Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); + Reservation r = new Reservation(workerGroup, c, new PeerBean(PeerBuilder.EMPTY_KEY_PAIR)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(conn, 0); @@ -240,7 +240,7 @@ public void testReservationTCPNonCleanShutdown() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsTCP(tcpMax); - Reservation r = new Reservation(workerGroup, c, new PeerBean(null)); + Reservation r = new Reservation(workerGroup, c, new PeerBean(PeerBuilder.EMPTY_KEY_PAIR)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); @@ -298,7 +298,7 @@ public void testReservationTCPNonCleanShutdown2() throws InterruptedException { ChannelClientConfiguration c = PeerBuilder.createDefaultChannelClientConfiguration(); c.pipelineFilter(new MyPipeLine()); c.maxPermitsTCP(tcpMax); - Reservation r = new Reservation(ev, c, new PeerBean(null)); + Reservation r = new Reservation(ev, c, new PeerBean(PeerBuilder.EMPTY_KEY_PAIR)); List fcc = new ArrayList(); for (int j = 0; j < inner; j++) { FutureChannelCreator fc = r.create(0, conn); From 90769decd18848df3cdab543e9f7ff25d0cb6da1 Mon Sep 17 00:00:00 2001 From: tbocek Date: Mon, 10 Aug 2015 22:36:50 +0200 Subject: [PATCH 063/135] fix null pointer for testcases --- core/src/main/java/net/tomp2p/connection/Reservation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 214dc2ce2..25d4f1f0e 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -373,7 +373,7 @@ public void run() { return; } - PeerSocketAddress psa = peerBean.serverPeerAddress().internalPeerSocketAddress(); + PeerSocketAddress psa = peerBean.serverPeerAddress() == null ? null: peerBean.serverPeerAddress().internalPeerSocketAddress(); InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, permitsUDP, permitsTCP, @@ -441,7 +441,7 @@ public void run() { return; } - PeerSocketAddress psa = peerBean.serverPeerAddress().internalPeerSocketAddress(); + PeerSocketAddress psa = peerBean.serverPeerAddress() == null ? null: peerBean.serverPeerAddress().internalPeerSocketAddress(); InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, 0, permitsPermanentTCP, From 4f461a3c67cfd96865cf2442bb9d6391d7adabcb Mon Sep 17 00:00:00 2001 From: tbocek Date: Mon, 10 Aug 2015 22:55:34 +0200 Subject: [PATCH 064/135] again, null pointer --- .../net/tomp2p/connection/Reservation.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 25d4f1f0e..ec88d7b90 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -19,6 +19,7 @@ import io.netty.channel.EventLoopGroup; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -373,8 +374,14 @@ public void run() { return; } - PeerSocketAddress psa = peerBean.serverPeerAddress() == null ? null: peerBean.serverPeerAddress().internalPeerSocketAddress(); - InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); + final InetAddress fromAddress; + if(peerBean.serverPeerAddress() == null) { + fromAddress = new InetSocketAddress(0).getAddress(); + } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { + fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); + } else { + fromAddress = peerBean.serverPeerAddress().inetAddress(); + } channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, permitsUDP, permitsTCP, channelClientConfiguration, fromAddress); @@ -441,8 +448,14 @@ public void run() { return; } - PeerSocketAddress psa = peerBean.serverPeerAddress() == null ? null: peerBean.serverPeerAddress().internalPeerSocketAddress(); - InetAddress fromAddress = psa == null ? peerBean.serverPeerAddress().inetAddress() : psa.inetAddress(); + final InetAddress fromAddress; + if(peerBean.serverPeerAddress() == null) { + fromAddress = new InetSocketAddress(0).getAddress(); + } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { + fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); + } else { + fromAddress = peerBean.serverPeerAddress().inetAddress(); + } channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, 0, permitsPermanentTCP, channelClientConfiguration, fromAddress); From fc838ca81ac7c5ad7e361577157c795830e9e2d8 Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 16 Aug 2015 23:56:13 +0200 Subject: [PATCH 065/135] work log: 13:15 - 14:55, 15:55 - 16:30, 22:15 - 23:55 - added UPNP testing and fixed other bugs --- .../net/tomp2p/connection/Reservation.java | 12 +- .../java/net/tomp2p/connection/Sender.java | 1 + .../tomp2p/p2p/builder/DiscoverBuilder.java | 6 +- .../net/tomp2p/peers/DefaultMaintenance.java | 3 +- .../main/java/net/tomp2p/peers/PeerMap.java | 21 ++- .../src/main/java/net/tomp2p/rpc/PingRPC.java | 2 +- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 1 + .../net/tomp2p/relay/DistributedRelay.java | 2 +- .../tomp2p/holep/manual/LocalNATUtils.java | 3 +- .../holep/manual/TestNATForwarding.java | 144 +++++++++++++-- .../net/tomp2p/holep/manual/TestNATLocal.java | 6 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 2 +- .../net/tomp2p/holep/manual/TestUPNP.java | 167 ++++++++++++++++++ nat/src/test/resources/logback.xml | 18 +- nat/src/test/resources/nat-net.sh | 2 +- 15 files changed, 347 insertions(+), 43 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index ec88d7b90..142e6cfb5 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -16,8 +16,6 @@ package net.tomp2p.connection; -import io.netty.channel.EventLoopGroup; - import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -34,15 +32,15 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.EventLoopGroup; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; import net.tomp2p.futures.FutureDone; import net.tomp2p.p2p.RequestConfiguration; import net.tomp2p.p2p.RoutingConfiguration; -import net.tomp2p.peers.PeerSocketAddress; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Reserves a block of connections. @@ -379,6 +377,8 @@ public void run() { fromAddress = new InetSocketAddress(0).getAddress(); } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); + } else if(peerBean.serverPeerAddress().isFirewalledTCP() || peerBean.serverPeerAddress().isFirewalledUDP() || peerBean.serverPeerAddress().isPortForwarding()){ + fromAddress = new InetSocketAddress(0).getAddress(); } else { fromAddress = peerBean.serverPeerAddress().inetAddress(); } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index bd3944f96..137e50843 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -883,6 +883,7 @@ public void operationComplete(FutureResponse future) throws Exception { } else if (message.command() == RPC.Commands.HOLEP.getNr() && message.type().ordinal() == Message.Type.REQUEST_3.ordinal()) { //do nothing, because such a (dummy) message will never reach its target the first time } + LOG.debug("peer failed: {}", message); synchronized (peerStatusListeners) { for (PeerStatusListener peerStatusListener : peerStatusListeners) { peerStatusListener.peerFailed(message.recipient(), new PeerException(future)); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index aa2c3c4eb..85fd7e31d 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -218,18 +218,20 @@ private void discover(final FutureDiscover futureDiscover, final PeerAddress pee final ChannelCreator cc, final ConnectionConfiguration configuration) { peer.pingRPC().addPeerReachableListener(new PeerReachable() { - private boolean changedUDP = false; + private volatile boolean changedUDP = false; - private boolean changedTCP = false; + private volatile boolean changedTCP = false; @Override public void peerWellConnected(PeerAddress peerAddress, PeerAddress reporter, boolean tcp) { if (tcp) { changedTCP = true; futureDiscover.discoveredTCP(); + LOG.debug("TCP discovered"); } else { changedUDP = true; futureDiscover.discoveredUDP(); + LOG.debug("UDP discovered"); } if (changedTCP && changedUDP) { futureDiscover.done(peerAddress, reporter); diff --git a/core/src/main/java/net/tomp2p/peers/DefaultMaintenance.java b/core/src/main/java/net/tomp2p/peers/DefaultMaintenance.java index 5b5a82017..2755db910 100644 --- a/core/src/main/java/net/tomp2p/peers/DefaultMaintenance.java +++ b/core/src/main/java/net/tomp2p/peers/DefaultMaintenance.java @@ -135,13 +135,14 @@ public PeerStatistic nextForMaintenance(Collection notInterestedAdd final PeerStatistic readyForMaintenance = next(mapNonVerified); if (readyForMaintenance != null && !notInterestedAddresses.contains(readyForMaintenance.peerAddress())) { - LOG.debug("check peer {} from the non-verified map.", readyForMaintenance.peerAddress()); + LOG.debug("check urgent peer {} from the non-verified map.", readyForMaintenance.peerAddress()); return readyForMaintenance; } } final PeerStatistic readyForMaintenance = next(mapVerified); if (readyForMaintenance != null && !notInterestedAddresses.contains(readyForMaintenance.peerAddress())) { + LOG.debug("check peer {} from the non-verified map.", readyForMaintenance.peerAddress()); return readyForMaintenance; } } diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index ad9dbc7df..470ed77dc 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -278,7 +278,7 @@ private boolean reject (PeerAddress peerAddress) { * @return True if the neighbor could be added or updated, otherwise false. */ @Override - public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referrer, final PeerConnection peerConnection, RTT roundTripTime) { + public boolean peerFound(PeerAddress remotePeer, final PeerAddress referrer, final PeerConnection peerConnection, RTT roundTripTime) { LOG.debug("Peer {} is online. Reporter was {}.", remotePeer, referrer); boolean firstHand = referrer == null; //if we got contacted by this peer, but we did not initiate the connection @@ -299,15 +299,24 @@ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referre // don't add nodes with zero node id, do not add myself and do not add // nodes marked as bad if (remotePeer.peerId().isZero() || self().equals(remotePeer.peerId()) || reject(remotePeer)) { + LOG.debug("peer Id is zero, self address, or simply rejected"); return false; } + //if we have first hand information, that means we send a message to that peer and we received a reply. + //So its not firewalled. This happens in the discovery phase if (remotePeer.isFirewalledTCP() || remotePeer.isFirewalledUDP()) { - return false; + if(firstHand) { + remotePeer = remotePeer.changeFirewalledTCP(false).changeFirewalledUDP(false); + } else { + LOG.debug("peer is firewalled, reject"); + return false; + } } //if a peer is relayed but cannot provide any relays, it is useless if (remotePeer.isRelayed() && remotePeer.peerSocketAddresses().isEmpty()) { + LOG.debug("relayed without any relays, reject"); return false; } @@ -315,8 +324,8 @@ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referre shutdownMap.containsKey(remotePeer.peerId()) || exceptionMap.containsKey(remotePeer.peerId()); - if(thirdHand && probablyDead) { - LOG.debug("Don't add {}.", remotePeer.peerId()); + if((secondHand || thirdHand) && probablyDead) { + LOG.debug("Most likely offline, reject"); return false; } @@ -329,8 +338,10 @@ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referre // we update the peer, so we can exit here and report that we have // updated it. notifyUpdate(remotePeer, old.element0()); + LOG.debug("Update peer information"); return true; } else if (old != null && !old.element1()) { + LOG.debug("Unreliable information, don't update"); //don't update, as we have second hand information that is not reliabel, we arleady have it, don't update return false; } @@ -359,10 +370,12 @@ public boolean peerFound(final PeerAddress remotePeer, final PeerAddress referre mapOverflow.remove(remotePeer.peerId()); } notifyInsert(remotePeer, true); + LOG.debug("Peer inserted"); return true; } } } + LOG.debug("Not rejected or inserted, add to overflow map"); // if we are here, we did not have this peer, but our verified map was full // check if we have it stored in the non verified map. final Map mapOverflow = peerMapOverflow.get(classMember); diff --git a/core/src/main/java/net/tomp2p/rpc/PingRPC.java b/core/src/main/java/net/tomp2p/rpc/PingRPC.java index 72db0a7ef..38b2dbe80 100644 --- a/core/src/main/java/net/tomp2p/rpc/PingRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/PingRPC.java @@ -319,7 +319,7 @@ public void handleResponse(final Message message, PeerConnection peerConnection, @Override public void operationComplete(final FutureChannelCreator future) throws Exception { if (future.isSuccess()) { - LOG.debug("Fire UDP to {}.", message.sender()); + LOG.debug("Fire UDP to {}.", message.sender()); FutureResponse futureResponse = fireUDP(message.sender(), future.channelCreator(), connectionBean().channelServer().channelServerConfiguration()); Utils.addReleaseListener(future.channelCreator(), futureResponse); diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index 9c2bd45b6..ff2bbdd47 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -171,6 +171,7 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { success = natUtils.mapUPNP(internalHost, peer.peerAddress().tcpPort(), peer.peerAddress().udpPort(), ports.udpPort(), ports.tcpPort()); } catch (Exception e) { + LOG.error("cannot map UPNP", e); success = false; } diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 6c5621f84..40352a639 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -145,7 +145,7 @@ public void run() { private List relayCandidates() { final List relayCandidates; - if (!relays.isEmpty()) { + if (relays.isEmpty()) { // Get the neighbors of this peer that could possibly act as relays. Relay // candidates are neighboring peers that are not relayed themselves and have // not recently failed as relay or denied acting as relay. diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 95116cbed..e4c2198dc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -231,8 +231,7 @@ public static Peer init(String ip, int port, int peerId) b.addAddress(InetAddress.getByName(ip)); ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); ccc.senderTCP(InetAddress.getByName(ip)); - Peer peer = new PeerBuilder(Number160.createHash(peerId)).channelClientConfiguration(ccc).ports(port).bindings(b) - .start(); + Peer peer = new PeerBuilder(Number160.createHash(peerId)).channelClientConfiguration(ccc).ports(port).bindings(b).behindFirewall().start(); System.out.println("Init "+peer.peerAddress()); return peer; } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java index e31a6f75f..38b7fff17 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -11,6 +11,7 @@ import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.FutureBootstrap; +import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; @@ -41,11 +42,9 @@ public void after() throws IOException, InterruptedException { } @Test - public void testForward() throws Exception { + public void testForwardTwoPeers() throws Exception { Peer relayPeer = null; - //System.exit(1); - RemotePeer unr1 = null; RemotePeer unr2 = null; try { @@ -78,20 +77,17 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - - //discover the 2nd relay - //peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); - //System.out.println("now we know peer realy2 "); - //final CountDownLatch cl2 = (CountDownLatch) get("cl2"); - //cl2.await(); + PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("peer2", fdir.object()); return "done"; } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(2000); System.err.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); - //return "d"; } }); @@ -115,27 +111,141 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - - //discover the 2nd relay - //peer1.discover().peerSocketAddress(relayAddress2).start().awaitUninterruptibly(); - //System.out.println("now we know peer realy2 "); - //final CountDownLatch cl2 = (CountDownLatch) get("cl2"); - //cl2.await(); + PeerAddress peer2 = new PeerAddress(Number160.createHash(0), "172.20.0.1", 4000, 4000); + FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("peer1", fdir.object()); return "done"; } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(2000); System.err.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); - //return "d"; } }); unr1.waitFor(); unr2.waitFor(); + Assert.assertEquals("done", unr1.getResult(1)); + Assert.assertEquals("done", unr2.getResult(1)); + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } + + @Test + public void testForwardTwoPlusOne() throws Exception { + Peer relayPeer = null; + + RemotePeer unr1 = null; + RemotePeer unr2 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); + final Peer regularPeer = LocalNATUtils.createRealNode(Number160.createHash(77), INF, 5003); + + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerAddress relay = relayPeer.peerAddress(); + System.out.println("relay peer at: "+relay); + + new Thread(new Runnable() { + + @Override + public void run() { + try { + Thread.sleep(5000); + PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + FutureDirect fdir = regularPeer.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("peer2", fdir.object()); + } catch (Exception e) { + e.printStackTrace(); + } finally { + regularPeer.shutdown().awaitUninterruptibly(); + } + + } + }).start(); + + //final Peer relayPeer1Copy = relayPeer1; + + unr1 = LocalNATUtils.executePeer(0, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, 4000, "peer1"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + Assert.assertTrue(fd1.isDiscoveredTCP()); + Thread.sleep(2000); + System.out.println("relay peer at1: "+relay); + BaseFuture fb = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + Thread.sleep(2000); + System.err.println(fb.failedReason()); + Assert.assertTrue(fb.isSuccess()); + return "done startup1"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + final Peer peer1 = (Peer) get("p1"); + PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("peer2", fdir.object()); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(5000); + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr2 = LocalNATUtils.executePeer(1, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, 4000, "peer2"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start().awaitUninterruptibly(); + Assert.assertTrue(fd1.isDiscoveredTCP()); + Thread.sleep(2000); + System.out.println("relay peer at2: "+relay); + BaseFuture fb = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + Thread.sleep(2000); + Assert.assertTrue(fb.isSuccess()); + return "done startup1"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + final Peer peer1 = (Peer) get("p1"); + PeerAddress peer2 = new PeerAddress(Number160.createHash(0), "172.20.0.1", 4000, 4000); + FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); + Assert.assertEquals("peer1", fdir.object()); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(5000); + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + unr2.waitFor(); Assert.assertEquals("done", unr1.getResult(1)); + Assert.assertEquals("done", unr2.getResult(1)); } finally { System.out.print("LOCAL> shutdown."); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index a508b38cc..005c81d32 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -35,7 +35,7 @@ * @author Thomas Bocek * */ -@Ignore +//@Ignore public class TestNATLocal implements Serializable { private static final long serialVersionUID = 1L; @@ -83,6 +83,10 @@ public Serializable execute() throws Exception { PeerNAT pn2 = new PeerBuilderNAT(peer2).start(); FutureNAT fn1 = pn1.portForwarding(fd1).awaitUninterruptibly(); FutureNAT fn2 = pn2.portForwarding(fd2).awaitUninterruptibly(); + + System.err.println("fn: "+fn1.failedReason()); + Assert.assertTrue(fn1.isSuccess()); + StringBuilder sb = new StringBuilder(); if(fn1.isSuccess() && fn2.isSuccess()) { // now peer1 and peer2 know each other locally. diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 79f6e8e26..a9b5f6598 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -212,7 +212,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { System.out.println("wait 5 sec"); - Thread.sleep(5000); + Thread.sleep(7000); System.out.println("done wait 5 sec"); //now relay1 is shutdown, check if we updated our data return "check relay2"; diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java new file mode 100644 index 000000000..bb4fe59c2 --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java @@ -0,0 +1,167 @@ +package net.tomp2p.holep.manual; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Random; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import net.tomp2p.dht.FuturePut; +import net.tomp2p.dht.PeerBuilderDHT; +import net.tomp2p.dht.PeerDHT; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.FutureDirect; +import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.nat.FutureNAT; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.storage.Data; + +public class TestUPNP implements Serializable { + + final static private Random RND = new Random(42); + static private Number160 relayPeerId = new Number160(RND); + //### CHANGE THIS TO YOUR INTERFACE### + final static private String INF = "eth1"; + + @Before + public void before() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("start", "0", "sym"); + LocalNATUtils.executeNatSetup("start", "1", "sym"); + LocalNATUtils.executeNatSetup("upnp", "0"); + LocalNATUtils.executeNatSetup("upnp", "1"); + } + + @After + public void after() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("stop", "0"); + LocalNATUtils.executeNatSetup("stop", "1"); + } + + @Test + public void testUPNP() throws Exception { + Peer relayPeer = null; + PeerDHT pd = null; + RemotePeer unr1 = null; + RemotePeer unr2 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); + pd = new PeerBuilderDHT(relayPeer).start(); + final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerAddress relay = relayPeer.peerAddress(); + System.out.println("relay peer at: "+relay); + + unr1 = LocalNATUtils.executePeer(0, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "peer1"); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start(); + PeerNAT pn = new PeerBuilderNAT(peer1).start(); + + FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); + System.err.println("fn: "+fn.failedReason()); + Assert.assertTrue(fn.isSuccess()); + + BaseFuture fb1 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + System.err.println(fb1.failedReason()); + Assert.assertTrue(fb1.isSuccess()); + + PeerDHT pd = new PeerBuilderDHT(peer1).start(); + put("pd", pd); + + Thread.sleep(5000); + BaseFuture fb2 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + System.err.println(fb2.failedReason()); + Assert.assertTrue(fb2.isSuccess()); + Assert.assertEquals(2, peer1.peerBean().peerMap().all().size()); + + return "done startup1"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(5000); + PeerDHT pd = (PeerDHT) get("pd"); + FuturePut fp = pd.put(Number160.ONE).data(new Data("test1")).start().awaitUninterruptibly(); + Assert.assertTrue(fp.isSuccess()); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(2000); + PeerDHT pd = (PeerDHT) get("pd"); + Assert.assertEquals(1, pd.storageLayer().get().size()); + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr2 = LocalNATUtils.executePeer(1, new Command() { + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, "peer2"); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress).start(); + PeerNAT pn = new PeerBuilderNAT(peer1).start(); + FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); + System.err.println("fn: "+fn.failedReason()); + Assert.assertTrue(fn.isSuccess()); + + BaseFuture fb1 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + System.err.println(fb1.failedReason()); + Assert.assertTrue(fb1.isSuccess()); + + PeerDHT pd = new PeerBuilderDHT(peer1).start(); + put("pd", pd); + + Thread.sleep(5000); + BaseFuture fb2 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); + System.err.println(fb2.failedReason()); + Assert.assertTrue(fb2.isSuccess()); + Assert.assertEquals(2, peer1.peerBean().peerMap().all().size()); + + return "done startup2"; + } + + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(7000); + return "done"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + Thread.sleep(2000); + PeerDHT pd = (PeerDHT) get("pd"); + Assert.assertEquals(1, pd.storageLayer().get().size()); + System.err.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + + unr1.waitFor(); + unr2.waitFor(); + Assert.assertEquals(1, pd.storageLayer().get().size()); + Assert.assertEquals("done", unr1.getResult(1)); + Assert.assertEquals("done", unr2.getResult(1)); + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer); + System.out.print("."); + LocalNATUtils.shutdown(unr1); + System.out.println("."); + } + } +} diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index 349bfcd3d..d3141d324 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -42,18 +42,24 @@ - + --> + - - - + + - - --> + + + + + + + + diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index 6b43ffc86..123fa50ba 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -154,7 +154,7 @@ upnp () { ip netns exec "nat$1" iptables -t nat -I PREROUTING -j MINIUPNPD ip netns exec "nat$1" iptables -t filter -N MINIUPNPD ip netns exec "nat$1" iptables -t filter -I FORWARD -j MINIUPNPD - ip netns exec "nat$1" miniupnpd -i nat$1_wan -a nat$1_lan + ip netns exec "nat$1" miniupnpd -i "nat$1_wan" -a "nat$1_lan" -P "/var/run/miniupnpd$1.pid" } case "$1" in From f1c6e36ee8076bff40942e0ae897dac981416389 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 17 Aug 2015 11:04:32 +0200 Subject: [PATCH 066/135] local NAT fixes --- .../net/tomp2p/connection/Reservation.java | 21 ++++++++++++++----- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 7 ++++--- nat/src/test/resources/logback.xml | 2 ++ nat/src/test/resources/nat-net.sh | 3 ++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 142e6cfb5..04480393a 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -16,8 +16,9 @@ package net.tomp2p.connection; +import java.net.Inet4Address; import java.net.InetAddress; -import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -374,18 +375,22 @@ public void run() { final InetAddress fromAddress; if(peerBean.serverPeerAddress() == null) { - fromAddress = new InetSocketAddress(0).getAddress(); + fromAddress = Inet4Address.getByAddress(new byte[4]); } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); - } else if(peerBean.serverPeerAddress().isFirewalledTCP() || peerBean.serverPeerAddress().isFirewalledUDP() || peerBean.serverPeerAddress().isPortForwarding()){ - fromAddress = new InetSocketAddress(0).getAddress(); } else { fromAddress = peerBean.serverPeerAddress().inetAddress(); } + + LOG.debug("channel from {}", fromAddress); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, permitsUDP, permitsTCP, channelClientConfiguration, fromAddress); addToSet(channelCreator); + } catch (UnknownHostException u) { + //never happens as we use wildcard address + u.printStackTrace(); + throw new RuntimeException(u); } finally { read.unlock(); } @@ -450,16 +455,22 @@ public void run() { final InetAddress fromAddress; if(peerBean.serverPeerAddress() == null) { - fromAddress = new InetSocketAddress(0).getAddress(); + fromAddress = Inet4Address.getByAddress(new byte[4]); } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); } else { fromAddress = peerBean.serverPeerAddress().inetAddress(); } + + LOG.debug("channel from {}", fromAddress); channelCreator = new ChannelCreator(workerGroup, futureChannelCreationShutdown, 0, permitsPermanentTCP, channelClientConfiguration, fromAddress); addToSet(channelCreator); + } catch (UnknownHostException u) { + //never happens as we use wildcard address + u.printStackTrace(); + throw new RuntimeException(u); } finally { read.unlock(); } diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index ff2bbdd47..ddd6eff09 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -106,7 +106,8 @@ public void operationComplete(FutureDiscover future) throws Exception { if (externalPorts != null) { final PeerAddress serverAddressOrig = peer.peerBean().serverPeerAddress(); final PeerAddress serverAddress = serverAddressOrig.changePorts(externalPorts.tcpPort(), - externalPorts.udpPort()).changeAddress(future.externalAddress()); + externalPorts.udpPort()).changeAddress(future.externalAddress()). + changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); // set the new address regardless wheter it will succeed // or not. @@ -123,12 +124,11 @@ public void operationComplete(FutureDiscover future) throws Exception { // UPNP or NAT-PMP was // successful, set flag PeerAddress newServerAddress = serverAddress.changePortForwarding(true); - newServerAddress = newServerAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); peer.peerBean().serverPeerAddress(newServerAddress); futureNAT.done(future.peerAddress(), future.reporter()); } else { // indicate relay - PeerAddress pa = peer.peerBean().serverPeerAddress() + PeerAddress pa = serverAddressOrig .changeFirewalledTCP(true).changeFirewalledUDP(true); peer.peerBean().serverPeerAddress(pa); futureNAT.failed(future); @@ -164,6 +164,7 @@ public void operationComplete(FutureDiscover future) throws Exception { * successful, otherwise null */ public Ports setupPortforwarding(final String internalHost, Ports ports) { + LOG.debug("setup UPNP for host {} and ports {}", internalHost, ports); // new random ports boolean success; diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index d3141d324..2dee3a675 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -44,11 +44,13 @@ --> + + diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index 123fa50ba..087bbf884 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -140,6 +140,7 @@ stop () { ip netns del "nat$1" ip link del "nat$1_real" killall -q miniupnpd + rm -f /var/run/miniupnpd*.pid } forward () { @@ -154,7 +155,7 @@ upnp () { ip netns exec "nat$1" iptables -t nat -I PREROUTING -j MINIUPNPD ip netns exec "nat$1" iptables -t filter -N MINIUPNPD ip netns exec "nat$1" iptables -t filter -I FORWARD -j MINIUPNPD - ip netns exec "nat$1" miniupnpd -i "nat$1_wan" -a "nat$1_lan" -P "/var/run/miniupnpd$1.pid" + ip netns exec "nat$1" miniupnpd -i "nat$1_wan" -a "nat$1_lan" -P "/var/run/miniupnpd$1.pid" -d > "/tmp/upnp$1.log" 2>&1 & } case "$1" in From ec42993d63492fd8b6f6272fb29525e032fe1312 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Sat, 29 Aug 2015 14:37:40 +0200 Subject: [PATCH 067/135] work log 11:30 - 14:45 - synced command execution for NAT test classes, fixed nat reflection, added initial version of stress test (not completed yet) --- .../connection/DefaultSendBehavior.java | 8 + .../java/net/tomp2p/connection/Sender.java | 16 +- .../main/java/net/tomp2p/message/Message.java | 16 ++ .../src/main/java/net/tomp2p/utils/Utils.java | 18 +- .../net/tomp2p/holep/manual/CommandSync.java | 32 +++ .../tomp2p/holep/manual/LocalNATUtils.java | 35 ++- .../net/tomp2p/holep/manual/RemotePeer.java | 3 + .../holep/manual/TestNATForwarding.java | 13 +- .../net/tomp2p/holep/manual/TestNATLocal.java | 6 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 26 +- .../tomp2p/holep/manual/TestNATStress.java | 259 ++++++++++++++++++ .../holep/manual/TestNATTypeDetection.java | 9 +- .../net/tomp2p/holep/manual/TestUPNP.java | 56 ++-- nat/src/test/resources/nat-net.sh | 4 +- 14 files changed, 430 insertions(+), 71 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/CommandSync.java create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java diff --git a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java index e268e0da1..752fef1e2 100644 --- a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java +++ b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java @@ -21,6 +21,10 @@ public SendMethod tcpSendBehavior(Message message) { // shortcut, just send to yourself return SendMethod.SELF; } + + if(message.isReflected()) { + return SendMethod.DIRECT; + } if (message.recipient().isRelayed()) { if (message.sender().isRelayed()) { @@ -53,6 +57,10 @@ public SendMethod udpSendBehavior(Message message) throws UnsupportedOperationEx // shortcut, just send to yourself return SendMethod.SELF; } + + if(message.isReflected()) { + return SendMethod.DIRECT; + } if (message.recipient().isRelayed() && message.sender().isRelayed() && !(message.command() == RPC.Commands.NEIGHBOR.getNr() || message.command() == RPC.Commands.PING.getNr())) { diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 137e50843..d567a743d 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -151,9 +151,12 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu // NAT reflection - rewrite recipient if we found a local address for // the recipient PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); - PeerSocketAddress orig = message.recipient().peerSocketAddress(); - message.saveOriginalRecipientBeforeTranslation(orig); - message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); + if(reflectedRecipient != null) { + PeerSocketAddress orig = message.recipient().peerSocketAddress(); + message.saveOriginalRecipientBeforeTranslation(orig); + message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); + message.reflected(); + } removePeerIfFailed(futureResponse, message); @@ -570,7 +573,12 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu // NAT reflection - rewrite recipient if we found a local address for // the recipient PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); - message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); + if(reflectedRecipient != null) { + PeerSocketAddress orig = message.recipient().peerSocketAddress(); + message.saveOriginalRecipientBeforeTranslation(orig); + message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); + message.reflected(); + } removePeerIfFailed(futureResponse, message); diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 84b2a2b32..ddd0d113f 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -204,6 +204,7 @@ public enum Type { private transient boolean verified = false; private transient boolean sendSelf = false; private transient PeerSocketAddress recipientBeforeTranslation = null; + private transient boolean reflected; /** * Creates message with a random ID. @@ -1296,4 +1297,19 @@ public Message saveOriginalRecipientBeforeTranslation(PeerSocketAddress recipien public PeerSocketAddress recipientBeforeTranslation() { return recipientBeforeTranslation; } + + public Message reflected(boolean reflected) { + this.reflected = reflected; + return this; + } + + public Message reflected() { + return reflected(true); + } + + public boolean isReflected() { + return reflected; + } + + } diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index 11771f22c..e915af0b8 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -930,23 +930,11 @@ public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress //check for NAT reflection if(recipient.inetAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null && recipient.internalPeerSocketAddress()!=null) { //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. - if(recipient.udpPort() == self.udpPort() ) { - //we send it to ourself, change it to something local - try { - - return new PeerSocketAddress(InetAddress.getLocalHost(), self.internalPeerSocketAddress().tcpPort(), - self.internalPeerSocketAddress().udpPort()); - } catch (UnknownHostException e) { - e.printStackTrace(); - return null; - } - } else { - InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); - return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); - } + InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); + return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); } } - return recipient.peerSocketAddress(); + return null; } /** diff --git a/nat/src/test/java/net/tomp2p/holep/manual/CommandSync.java b/nat/src/test/java/net/tomp2p/holep/manual/CommandSync.java new file mode 100644 index 000000000..8d8a418b2 --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/CommandSync.java @@ -0,0 +1,32 @@ +package net.tomp2p.holep.manual; + +import java.util.concurrent.CountDownLatch; + +public class CommandSync { + + final private int nrPeers; + + private CountDownLatch[] latches; + + public CommandSync(int nrPeers) { + this.nrPeers = nrPeers; + } + + public void init(int nrCmds) { + if(latches != null) { + if(latches.length != nrCmds) { + throw new RuntimeException("commands length mismatch"); + } + return; + } + latches = new CountDownLatch[nrCmds]; + for(int i=0;i klass, int nr, final Command... cmd) + public static RemotePeer executePeer(Class klass, int nr, final CommandSync sync, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { - return executePeer(LocalNATUtils.class, nr, DEFAULT_CALLBACK, cmd); + return executePeer(LocalNATUtils.class, nr, DEFAULT_CALLBACK, sync, cmd); } - public static RemotePeer executePeer(Class klass, final int nr, final RemotePeerCallback remoteCallback, final Command... cmd) + public static RemotePeer executePeer(Class klass, final int nr, final RemotePeerCallback remoteCallback, final CommandSync sync, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { + + sync.init(cmd.length); + String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator + "java"; @@ -125,6 +128,9 @@ public void run() { Object o = fromString(line); results.set(i, o); done = true; + sync.waitFor(i); + process.getOutputStream().write(77); + process.getOutputStream().flush(); } else { System.out.println("OUT["+nr+"]>" + line); } @@ -211,8 +217,23 @@ public static void handleMain(String[] args) throws ClassNotFoundException, IOEx final Command[] cmds = LocalNATUtils.toObjects(args); for(Command cmd:cmds) { try { + final CountDownLatch latch = new CountDownLatch(1); + new Thread(new Runnable() { + @Override + public void run() { + try { + System.in.read(); + } catch (IOException e) { + e.printStackTrace(); + } + latch.countDown(); + + } + }).start(); Serializable result = cmd.execute(); System.out.println(TAG + LocalNATUtils.toString(result)); + //wait until we can continue + latch.await(); } catch (Throwable e) { e.printStackTrace(); System.out.println(TAG + LocalNATUtils.toString(e.getMessage())); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java index aa15f26f1..80bc4d4de 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java @@ -32,5 +32,8 @@ public Object getResult(int i) { public Command getCmd(int i) { return cmd[i]; } + public int resultSize() { + return results.length(); + } } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java index 38b7fff17..8d69eecb9 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -25,7 +25,7 @@ public class TestNATForwarding implements Serializable { final static private Random RND = new Random(42); static private Number160 relayPeerId = new Number160(RND); //### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "eth1"; + final static private String INF = "enp0s25"; @Before public void before() throws IOException, InterruptedException { @@ -55,8 +55,8 @@ public void testForwardTwoPeers() throws Exception { System.out.println("relay peer at: "+relay); //final Peer relayPeer1Copy = relayPeer1; - - unr1 = LocalNATUtils.executePeer(0, new Command() { + CommandSync sync = new CommandSync(2); + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, 4000, "peer1"); @@ -91,7 +91,7 @@ public Serializable execute() throws Exception { } }); - unr2 = LocalNATUtils.executePeer(1, new Command() { + unr2 = LocalNATUtils.executePeer(1, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, 4000, "peer2"); @@ -152,6 +152,7 @@ public void testForwardTwoPlusOne() throws Exception { final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); + CommandSync sync = new CommandSync(2); new Thread(new Runnable() { @@ -173,7 +174,7 @@ public void run() { //final Peer relayPeer1Copy = relayPeer1; - unr1 = LocalNATUtils.executePeer(0, new Command() { + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, 4000, "peer1"); @@ -208,7 +209,7 @@ public Serializable execute() throws Exception { } }); - unr2 = LocalNATUtils.executePeer(1, new Command() { + unr2 = LocalNATUtils.executePeer(1, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, 4000, "peer2"); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 005c81d32..28867e3d2 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -41,7 +41,7 @@ public class TestNATLocal implements Serializable { private static final long serialVersionUID = 1L; //### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "eth1"; + final static private String INF = "enp0s25"; final static private Random RND = new Random(42); static private Number160 relayPeerId = new Number160(RND); @@ -67,8 +67,8 @@ public void testLocalSend() throws Exception { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); - - unr1 = LocalNATUtils.executePeer(0, new Command() { + CommandSync sync = new CommandSync(1); + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index a9b5f6598..80f626a30 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -39,7 +39,7 @@ public class TestNATRelay implements Serializable { static private Number160 relayPeerId4 = new Number160(RND); static private Number160 relayPeerId5 = new Number160(RND); //### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "eth1"; + final static private String INF = "enp0s25"; @Before public void before() throws IOException, InterruptedException { @@ -72,6 +72,7 @@ public void testRelayFailover1() throws Exception { final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); final Peer relayPeer1Copy = relayPeer1; + CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, new RemotePeerCallback() { @@ -86,7 +87,7 @@ public void onFinished(int i) { relayPeer1Copy.shutdown().awaitUninterruptibly(); } } - }, new Command() { + }, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -165,6 +166,7 @@ public void testRelayFailover2() throws Exception { final Peer relayPeer1Copy = relayPeer1; final Peer relayPeer2Copy = relayPeer2; final AtomicBoolean test = new AtomicBoolean(false); + CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, new RemotePeerCallback() { @Override @@ -183,7 +185,7 @@ public void onFinished(int i) { } } - }, new Command() { + }, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -262,7 +264,8 @@ public void testFullRelay() throws Exception { final PeerSocketAddress relayAddress4 = relayPeer4.peerAddress().peerSocketAddress(); relayPeer5 = createRelay(relayPeerId5, 5006); final PeerSocketAddress relayAddress5 = relayPeer5.peerAddress().peerSocketAddress(); - unr1 = LocalNATUtils.executePeer(0, new Command() { + CommandSync sync = new CommandSync(1); + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -328,8 +331,9 @@ public void testLateRelay() throws Exception { final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); relayPeer2 = createRelay(relayPeerId2, 5003); final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + CommandSync sync = new CommandSync(1); - unr1 = LocalNATUtils.executePeer(0, new Command() { + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -453,8 +457,9 @@ public void testRealRelayDifferentNAT() throws Exception { try { relayPeer = createRelay(relayPeerId1, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + CommandSync sync = new CommandSync(2); - unr1 = LocalNATUtils.executePeer(0, new Command() { + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -495,7 +500,7 @@ public Serializable execute() throws Exception { }); - unr2 = LocalNATUtils.executePeer(1, new Command() { + unr2 = LocalNATUtils.executePeer(1, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -552,7 +557,8 @@ public void testRealRelaySameNATNoRelay() throws Exception { RemotePeer unr1 = null; try { - unr1 = LocalNATUtils.executePeer(0, new Command() { + CommandSync sync = new CommandSync(1); + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { @@ -605,8 +611,8 @@ public void testRealRelaySameNAT() throws Exception { try { relayPeer = createRelay(relayPeerId1, 5002); final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); - - unr1 = LocalNATUtils.executePeer(0, new Command() { + CommandSync sync = new CommandSync(1); + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java new file mode 100644 index 000000000..3a7a48b8e --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -0,0 +1,259 @@ +package net.tomp2p.holep.manual; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Random; +import java.util.concurrent.CountDownLatch; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import net.tomp2p.connection.PeerConnection; +import net.tomp2p.dht.PeerDHT; +import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.nat.FutureNAT; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.relay.RelayCallback; + +/** + * 2 UPNP peers behind same NAT, 1 behind other NAT (total 3 peers) 2 port + * forwarding peers behind same NAT, 1 behind other NAT (total 3 peers) 2 + * relayed peers behind same NAT, 1 behind other NAT (total 3 peers) + * + * In total 9 peers (without relays) + * + * @author Thomas Bocek + * + */ +public class TestNATStress implements Serializable { + + final static private Random RND = new Random(42); + static private Number160 relayPeerId1 = new Number160(RND); + static private Number160 relayPeerId2 = new Number160(RND); + // ### CHANGE THIS TO YOUR INTERFACE### + final static private String INF = "enp0s25"; + + @Before + public void before() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("start", "0"); + LocalNATUtils.executeNatSetup("start", "1"); + LocalNATUtils.executeNatSetup("upnp", "0"); + LocalNATUtils.executeNatSetup("upnp", "1"); + LocalNATUtils.executeNatSetup("start", "2", "sym"); + LocalNATUtils.executeNatSetup("start", "3", "sym"); + LocalNATUtils.executeNatSetup("forward", "2", "4000", "10.0.2.2", "5000"); + LocalNATUtils.executeNatSetup("forward", "2", "4000", "10.0.2.3", "5000"); + LocalNATUtils.executeNatSetup("forward", "3", "4000", "10.0.3.2", "5000"); + LocalNATUtils.executeNatSetup("start", "4", "sym"); + LocalNATUtils.executeNatSetup("start", "5", "sym"); + } + + @After + public void after() throws IOException, InterruptedException { + LocalNATUtils.executeNatSetup("stop", "0"); + LocalNATUtils.executeNatSetup("stop", "1"); + LocalNATUtils.executeNatSetup("stop", "2"); + LocalNATUtils.executeNatSetup("stop", "3"); + LocalNATUtils.executeNatSetup("stop", "4"); + LocalNATUtils.executeNatSetup("stop", "5"); + } + + @Test + public void testStress() throws Exception { + Peer relayPeer1 = null; + Peer relayPeer2 = null; + + PeerDHT pd = null; + RemotePeer unr[] = new RemotePeer[9]; + CommandSync sync = new CommandSync(9); + + try { + relayPeer1 = createRelay(relayPeerId1, 5002); + relayPeer2 = createRelay(relayPeerId2, 5003); + final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + + System.out.println("relay 1:"+relayPeer1.peerAddress()); + System.out.println("relay 2:"+relayPeer2.peerAddress()); + + unr[0] = LocalNATUtils.executePeer(0, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); + PeerNAT pn = new PeerBuilderNAT(peer1).start(); + FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); + return fn.isSuccess(); + } + }); + + unr[1] = LocalNATUtils.executePeer(0, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.0.3", 5000, 1); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); + PeerNAT pn = new PeerBuilderNAT(peer1).start(); + FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); + return fn.isSuccess(); + } + }); + + unr[2] = LocalNATUtils.executePeer(1, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 2); + put("p1", peer1); + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); + PeerNAT pn = new PeerBuilderNAT(peer1).start(); + FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); + return fn.isSuccess(); + } + }); + + unr[3] = LocalNATUtils.executePeer(2, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.2.2", 5000, 3, 4000); + put("p1", peer1); + FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + return fd.isSuccess(); + } + }); + + unr[4] = LocalNATUtils.executePeer(2, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.2.3", 5000, 4, 4000); + put("p1", peer1); + FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + return fd.isSuccess(); + } + }); + + unr[5] = LocalNATUtils.executePeer(3, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.3.2", 5000, 5, 4000); + put("p1", peer1); + FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + return fd.isSuccess(); + } + }); + + unr[6] = LocalNATUtils.executePeer(4, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.4.2", 5000, 6); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + + final CountDownLatch cl1 = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl1)).start(); + //setup relay + pn1.startRelay(); + cl1.await(); + return "true"; + } + }); + + unr[7] = LocalNATUtils.executePeer(4, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.init("10.0.4.3", 5000, 7); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + + final CountDownLatch cl1 = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl1)).start(); + //setup relay + pn1.startRelay(); + cl1.await(); + return "true"; + } + }); + + unr[8] = LocalNATUtils.executePeer(5, sync, new Command() { + + @Override + public Serializable execute() throws Exception { + Peer peer1 = LocalNATUtils.createNattedPeer("10.0.5.2", 5000, 8, "me1"); + put("p1", peer1); + + FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Assert.assertFalse(fd1.isDiscoveredTCP()); + + final CountDownLatch cl1 = new CountDownLatch(1); + PeerNAT pn1 = new PeerBuilderNAT(peer1).relayCallback(countDownRelayCallback(cl1)).start(); + //setup relay + pn1.startRelay(); + cl1.await(); + return "true"; + } + }); + + + + for (RemotePeer u : unr) { + u.waitFor(); + } + + for (RemotePeer u : unr) { + for (int i = 0; i < u.resultSize(); i++) { + Assert.assertEquals("true", u.getResult(i)); + } + } + + } finally { + System.out.print("LOCAL> shutdown."); + LocalNATUtils.shutdown(relayPeer1, relayPeer2); + System.out.print("."); + LocalNATUtils.shutdown(unr); + System.out.println("."); + } + } + + private RelayCallback countDownRelayCallback( + final CountDownLatch cl) { + return new RelayCallback() { + @Override + public void onRelayRemoved(PeerAddress candidate, PeerConnection object) {} + @Override + public void onRelayAdded(PeerAddress candidate, PeerConnection object) {cl.countDown();} + @Override + public void onFailure(Exception e) {e.printStackTrace();} + @Override + public void onFullRelays(int activeRelays) {} + @Override + public void onNoMoreRelays(int activeRelays) {} + @Override + public void onShutdown() {} + }; + } + + private Peer createRelay(Number160 relayPeerId, int port) throws Exception { + Peer relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, port); + new PeerBuilderNAT(relayPeer).start(); + return relayPeer; + } +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index 9100087b4..c3ba735fb 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -35,14 +35,14 @@ * @author Thomas Bocek * */ -@Ignore +//@Ignore public class TestNATTypeDetection 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 = "eth1"; + final static private String INF = "enp0s25"; static private Number160 relayPeerId = new Number160(RND); @@ -76,7 +76,8 @@ public void testDetection() throws Exception { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); final String address = relayAddress.getHostAddress(); - unr1 = LocalNATUtils.executePeer(0, + CommandSync sync = new CommandSync(2); + unr1 = LocalNATUtils.executePeer(0, sync, new Command[] { new Command() { // startup @Override @@ -101,7 +102,7 @@ public Serializable execute() throws Exception { } } }); - unr2 = LocalNATUtils.executePeer(1, + unr2 = LocalNATUtils.executePeer(1, sync, new Command[] { new Command() { // startup @Override diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java index bb4fe59c2..8de9cd649 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java @@ -13,7 +13,6 @@ import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; import net.tomp2p.nat.PeerBuilderNAT; @@ -29,7 +28,7 @@ public class TestUPNP implements Serializable { final static private Random RND = new Random(42); static private Number160 relayPeerId = new Number160(RND); //### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "eth1"; + final static private String INF = "enp0s25"; @Before public void before() throws IOException, InterruptedException { @@ -57,8 +56,10 @@ public void testUPNP() throws Exception { final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); + + CommandSync sync = new CommandSync(2); - unr1 = LocalNATUtils.executePeer(0, new Command() { + unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.0.2", 5000, 0, "peer1"); @@ -77,36 +78,45 @@ public Serializable execute() throws Exception { PeerDHT pd = new PeerBuilderDHT(peer1).start(); put("pd", pd); - Thread.sleep(5000); BaseFuture fb2 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); System.err.println(fb2.failedReason()); Assert.assertTrue(fb2.isSuccess()); - Assert.assertEquals(2, peer1.peerBean().peerMap().all().size()); - - return "done startup1"; + Assert.assertEquals(1, peer1.peerBean().peerMap().all().size()); + return ""+(peer1.peerBean().peerMap().all().size() == 1); } }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { PeerDHT pd = (PeerDHT) get("pd"); FuturePut fp = pd.put(Number160.ONE).data(new Data("test1")).start().awaitUninterruptibly(); Assert.assertTrue(fp.isSuccess()); - return "done"; + return "" + fp.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(2000); + //Thread.sleep(2000); PeerDHT pd = (PeerDHT) get("pd"); + String retVal = "" + (1 == pd.storageLayer().get().size()); Assert.assertEquals(1, pd.storageLayer().get().size()); System.err.println("shutdown"); - return LocalNATUtils.shutdown((Peer)get("p1")); + LocalNATUtils.shutdown((Peer)get("p1")); + return retVal; } }); - unr2 = LocalNATUtils.executePeer(1, new Command() { + unr2 = LocalNATUtils.executePeer(1, sync, new Command() { + @Override + public Serializable execute() throws Exception { + return "true"; + } + }, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.createNattedPeer("10.0.1.2", 5000, 1, "peer2"); @@ -124,37 +134,43 @@ public Serializable execute() throws Exception { PeerDHT pd = new PeerBuilderDHT(peer1).start(); put("pd", pd); - Thread.sleep(5000); + //Thread.sleep(5000); BaseFuture fb2 = peer1.bootstrap().peerAddress(relay).start().awaitUninterruptibly(); System.err.println(fb2.failedReason()); Assert.assertTrue(fb2.isSuccess()); Assert.assertEquals(2, peer1.peerBean().peerMap().all().size()); - return "done startup2"; + return "" + (peer1.peerBean().peerMap().all().size() == 2); } }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(7000); - return "done"; + return "true"; } }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(2000); PeerDHT pd = (PeerDHT) get("pd"); + String retVal = "" + (1 == pd.storageLayer().get().size()); Assert.assertEquals(1, pd.storageLayer().get().size()); System.err.println("shutdown"); - return LocalNATUtils.shutdown((Peer)get("p1")); + LocalNATUtils.shutdown((Peer)get("p1")); + return retVal; } }); unr1.waitFor(); unr2.waitFor(); Assert.assertEquals(1, pd.storageLayer().get().size()); - Assert.assertEquals("done", unr1.getResult(1)); - Assert.assertEquals("done", unr2.getResult(1)); + + for(int i=0;i shutdown."); diff --git a/nat/src/test/resources/nat-net.sh b/nat/src/test/resources/nat-net.sh index 087bbf884..69428f9c1 100755 --- a/nat/src/test/resources/nat-net.sh +++ b/nat/src/test/resources/nat-net.sh @@ -129,8 +129,8 @@ start () { fi #if we have a drop policy, we need this accept rules - #ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_wan" -o "nat$1_lan" -m state --state RELATED,ESTABLISHED -j ACCEPT - #ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_lan" -o "nat$1_wan" -j ACCEPT + ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_wan" -o "nat$1_lan" -m state --state RELATED,ESTABLISHED -j ACCEPT + ip netns exec "nat$1" iptables -A FORWARD -i "nat$1_lan" -o "nat$1_wan" -j ACCEPT echo "NAT setup $2". } From 5af1fad2a78d16f64e7ffa5278262179f7f3d7df Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 30 Aug 2015 23:14:18 +0200 Subject: [PATCH 068/135] work log: 21:15 - 23:15 relay fixes and stress test setup --- .../net/tomp2p/connection/RequestHandler.java | 1 + .../java/net/tomp2p/connection/Sender.java | 2 + .../main/java/net/tomp2p/relay/RelayRPC.java | 10 ++- .../java/net/tomp2p/relay/RelayUtils.java | 1 + .../tomp2p/holep/manual/TestNATStress.java | 76 +++++++++++++++++-- nat/src/test/resources/logback.xml | 16 ++-- 6 files changed, 94 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index b897b22f6..9a9723e7a 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -305,6 +305,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo // We got a good answer, let's mark the sender as alive //if its an announce, the peer status will be handled in the RPC if (responseMessage.isOk() || responseMessage.isNotOk()) { + LOG.debug("Try adding peer {} to map, {}", responseMessage.sender(), responseMessage); peerBean.notifyPeerFound(responseMessage.sender(), null, null, futureResponse.getRoundTripTime()); } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index d567a743d..7e107d87e 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -156,6 +156,7 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu message.saveOriginalRecipientBeforeTranslation(orig); message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); message.reflected(); + LOG.debug("reflect recipient TCP {}", message); } removePeerIfFailed(futureResponse, message); @@ -578,6 +579,7 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu message.saveOriginalRecipientBeforeTranslation(orig); message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); message.reflected(); + LOG.debug("reflect recipient UDP {}", message); } removePeerIfFailed(futureResponse, message); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index c2ea22482..4567356aa 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -6,6 +6,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -230,7 +231,14 @@ private Dispatcher dispatcher() { */ private void handleSetup(Message message, final PeerConnection unreachablePeerConnectionOrig, final Responder responder) { final Number160 unreachablePeerId = unreachablePeerConnectionOrig.remotePeer().peerId(); - final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer(unreachablePeerConnectionOrig.remotePeer().changeRelayed(true)); + //add myself as relay + Collection psa = unreachablePeerConnectionOrig.remotePeer().peerSocketAddresses(); + Collection psa2 = new ArrayList(psa); + + psa2.add(peer().peerAddress().peerSocketAddress()); + final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer( + unreachablePeerConnectionOrig.remotePeer().changeRelayed(true).changePeerSocketAddresses(psa2)); + //now we can add this peer to the map, as we have now set the flag peerBean().notifyPeerFound(message.sender(), message.sender(), unreachablePeerConnectionCopy, null); for (Commands command : RPC.Commands.values()) { diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 577b427e0..b652df54e 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -58,6 +58,7 @@ public static List> unflatten(Collection --> - - - - - - + + + + + + + + + + From 2dfd0116f755ce96af50264d6de8c3e16498fdad Mon Sep 17 00:00:00 2001 From: tbocek Date: Sun, 30 Aug 2015 23:49:36 +0200 Subject: [PATCH 069/135] added french message --- core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java b/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java index 45a851900..d6dd62efe 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java +++ b/core/src/main/java/net/tomp2p/message/TomP2PCumulationTCP.java @@ -136,6 +136,8 @@ public void exceptionCaught(final ChannelHandlerContext ctx, .getMessage() .equals("Eine vorhandene Verbindung wurde vom Remotehost geschlossen")) { return; + } else if (cause.getMessage().equals("Connexion ré-initialisée par le correspondant")) { + return; } if (msg == null && decoder.lastContent() == null) { LOG.error("Exception in decoding TCP. Occurred before starting to decode.", cause); From 2a839085d1e0e736e3601971ac6453905623fbeb Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 15:17:13 +0200 Subject: [PATCH 070/135] better debug output --- .../java/net/tomp2p/peers/PeerAddress.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index d4b9e468c..35315e940 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -552,17 +552,36 @@ public byte relays() { @Override public String toString() { StringBuilder sb = new StringBuilder("paddr["); - sb.append(peerId.toString()).append(peerSocketAddress.toString()).append("]"); - sb.append("/relay(").append(relayed); + sb.append(peerId.toString()).append(peerSocketAddress.toString()).append(','); + + if(net6) { + sb.append('6'); + } + if(firewalledTCP) { + sb.append('t'); + } + if(firewalledUDP) { + sb.append('u'); + } + if(relayed) { + sb.append('r'); + } + if(slow) { + sb.append('s'); + } + if(portForwarding) { + sb.append('p'); + } + if(net4Private) { + sb.append('4'); + } + sb.append(']'); + if (relayed) { - sb.append(",").append(peerSocketAddresses.size()).append(")=") + sb.append("r:(").append(peerSocketAddresses.size()).append(")") .append(Arrays.toString(peerSocketAddresses.toArray())); - } else { - sb.append(")"); } - sb.append("/slow(").append(slow).append(")"); - return sb.toString(); } From 8eb47c76b4d3e12f3a1d4f21afe17bd854b5a2bb Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 15:17:28 +0200 Subject: [PATCH 071/135] better debug output --- core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java index 5c76f7f2e..06e3e76b0 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java @@ -248,14 +248,14 @@ public boolean isIPv4() { @Override public String toString() { - StringBuilder sb = new StringBuilder("["); + StringBuilder sb = new StringBuilder(); sb.append(inetAddress); if(tcpPort == udpPort) { sb.append(",").append(tcpPort); } else { sb.append(",t:").append(tcpPort).append(",u:").append(udpPort); } - return sb.append("]").toString(); + return sb.toString(); } @Override From 59e182e98e3dfbb56f71a5e738ae95437d005db3 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 15:18:16 +0200 Subject: [PATCH 072/135] don't change slow flag --- nat/src/main/java/net/tomp2p/relay/DistributedRelay.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 40352a639..0774b0a66 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -320,7 +320,7 @@ private void updatePeerAddress() { // update firewalled and isRelayed flags PeerAddress newAddress = peer.peerAddress().changeFirewalledTCP(!hasRelays).changeFirewalledUDP(!hasRelays) - .changeRelayed(hasRelays).changePeerSocketAddresses(socketAddresses).changeSlow(hasRelays); + .changeRelayed(hasRelays).changePeerSocketAddresses(socketAddresses); peer.peerBean().serverPeerAddress(newAddress); LOG.debug("Updated peer address {}, isrelay = {}", newAddress, hasRelays); } From 945850c4bcc98b465e65b8b2f491204b5be814a6 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 18:54:43 +0200 Subject: [PATCH 073/135] change to cachemap for better resource control --- .../java/net/tomp2p/connection/Sender.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 7e107d87e..b395f6f3e 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -16,14 +16,6 @@ package net.tomp2p.connection; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.util.concurrent.EventExecutorGroup; -import io.netty.util.concurrent.GenericFutureListener; - import java.net.ConnectException; import java.net.InetSocketAddress; import java.nio.channels.ClosedChannelException; @@ -34,10 +26,19 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.CancellationException; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReferenceArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.util.concurrent.EventExecutorGroup; +import io.netty.util.concurrent.GenericFutureListener; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.Cancel; import net.tomp2p.futures.FutureDone; @@ -60,12 +61,10 @@ import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.storage.Data; +import net.tomp2p.utils.ConcurrentCacheMap; import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * The class that sends out messages. * @@ -85,7 +84,7 @@ public class Sender { // this map caches all messages which are meant to be sent by a reverse // connection setup - private final ConcurrentHashMap> cachedRequests = new ConcurrentHashMap>(); + private final ConcurrentCacheMap> cachedRequests = new ConcurrentCacheMap>(30, 1024); private PingBuilderFactory pingBuilderFactory; @@ -910,7 +909,7 @@ public void operationComplete(FutureResponse future) throws Exception { * reverse connection is set up beforehand. After a successful connection * establishment, the cached messages are sent through the direct channel. */ - public ConcurrentHashMap> cachedRequests() { + public ConcurrentCacheMap> cachedRequests() { return cachedRequests; } From 66498ac018c18abd40f67584ca1e8feac3d173e8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 18:55:44 +0200 Subject: [PATCH 074/135] fixes for IPv4 and better toString for debugging --- core/src/main/java/net/tomp2p/peers/IP.java | 44 +++++++++++++++++-- .../java/net/tomp2p/peers/PeerAddress.java | 19 +++++--- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/net/tomp2p/peers/IP.java b/core/src/main/java/net/tomp2p/peers/IP.java index 40a1a3f12..34607dac6 100644 --- a/core/src/main/java/net/tomp2p/peers/IP.java +++ b/core/src/main/java/net/tomp2p/peers/IP.java @@ -19,8 +19,12 @@ private IPv4(int bits) { public IPv4 maskWithNetworkMask(final int networkMask) { if (networkMask == 32) { return this; - } else { - return new IPv4(bits & (0xFFFFFFFF << (32 - networkMask))); + } else if(networkMask == 0) { + return new IPv4(0); + } + else { + int mask = (0xFFFFFFFF << (32 - networkMask)); + return new IPv4(bits & mask); } } @@ -28,7 +32,7 @@ public IPv4 maskWithNetworkMask(final int networkMask) { * 192.168.1.2 with netmask /24 results in 0.0.0.2 */ public IPv4 maskWithNetworkMaskInv(final int networkMask) { - if (networkMask == 32) { + if (networkMask == 0) { return this; } else { return new IPv4(bits & (0xFFFFFFFF >>> networkMask)); @@ -71,6 +75,19 @@ public boolean equals(Object obj) { public int hashCode() { return bits; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("/"); + sb.append((byte) (bits >>> 24)); + sb.append('.'); + sb.append((byte) (bits >>> 16)); + sb.append('.'); + sb.append((byte) (bits >>> 8)); + sb.append('.'); + sb.append((byte) bits); + return sb.toString(); + } } @@ -134,6 +151,27 @@ public boolean equals(Object obj) { public int hashCode() { return (int)((highBits^(highBits>>>32)) ^ (lowBits^(lowBits>>>32))); } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("/"); + sb.append(String.format("%04X ", (short) (highBits >>> 48))); + sb.append(':'); + sb.append(String.format("%04X ", (short) (highBits >>> 32))); + sb.append(':'); + sb.append(String.format("%04X ", (short) (highBits >>> 16))); + sb.append(':'); + sb.append(String.format("%04X ", (short) highBits)); + sb.append(':'); + sb.append(String.format("%04X ", (short) (lowBits >>> 48))); + sb.append(':'); + sb.append(String.format("%04X ", (short) (lowBits >>> 32))); + sb.append(':'); + sb.append(String.format("%04X ", (short) (lowBits >>> 16))); + sb.append(':'); + sb.append(String.format("%04X ", (short) lowBits)); + return sb.toString(); + } } public static IPv4 fromInet4Address(final InetAddress inetAddress) { diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 35315e940..17f43641e 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import java.io.Serializable; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -31,6 +32,8 @@ import java.util.Collection; import java.util.Collections; +import javax.management.RuntimeErrorException; + import net.tomp2p.utils.Utils; /** @@ -300,7 +303,7 @@ public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress int size = Number160.BYTE_ARRAY_SIZE; this.peerSocketAddress = peerSocketAddress; this.internalPeerSocketAddress = internalPeerSocketAddress; - this.internalNetworkPrefix = internalPeerSocketAddress == null ? -1: prefix(internalPeerSocketAddress.inetAddress()); + this.internalNetworkPrefix = internalPeerSocketAddress == null ? -1: prefix4(internalPeerSocketAddress.inetAddress()); this.hashCode = id.hashCode(); this.net6 = peerSocketAddress.inetAddress() instanceof Inet6Address; this.firewalledUDP = firewalledUDP; @@ -932,7 +935,7 @@ public InetAddress calcInternalInetAddress(InetAddress remote) { return mask.set(masked).toInetAddress(); } - private int prefix(InetAddress inetAddress) { + private int prefix4(InetAddress inetAddress) { NetworkInterface networkInterface; try { networkInterface = NetworkInterface.getByInetAddress(internalPeerSocketAddress.inetAddress()); @@ -942,11 +945,15 @@ private int prefix(InetAddress inetAddress) { if(networkInterface.getInterfaceAddresses().size() <= 0) { return -1; } - InterfaceAddress iface = networkInterface.getInterfaceAddresses().get(0); - if(iface == null) { - return -1; + for(InterfaceAddress iface: networkInterface.getInterfaceAddresses()) { + if(iface == null) { + continue; + } + if(iface.getAddress() instanceof Inet4Address) { + return iface.getNetworkPrefixLength(); + } } - return iface.getNetworkPrefixLength(); + return -1; } catch (SocketException e) { e.printStackTrace(); return -1; From f18933300e4bd2342ff5febcd02dc519413eff95 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 18:56:45 +0200 Subject: [PATCH 075/135] reflection does not need to work with portforwarding only --- core/src/main/java/net/tomp2p/utils/Utils.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index e915af0b8..de7c57312 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -926,13 +926,12 @@ public static int randomPositiveInt(int upperBound) { } public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress self) { - if(self.isPortForwarding() && recipient.isPortForwarding()) { - //check for NAT reflection - if(recipient.inetAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null && recipient.internalPeerSocketAddress()!=null) { - //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. - InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); - return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); - } + + //check for NAT reflection + if(recipient.inetAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null && recipient.internalPeerSocketAddress()!=null) { + //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. + InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); + return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); } return null; } From 9569fc6b272257ed0262db1003df00edbd8a544e Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 18:57:07 +0200 Subject: [PATCH 076/135] new tests for IP mask calculation --- .../test/java/net/tomp2p/peers/TestIP.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/core/src/test/java/net/tomp2p/peers/TestIP.java b/core/src/test/java/net/tomp2p/peers/TestIP.java index fdd5f029e..372466078 100644 --- a/core/src/test/java/net/tomp2p/peers/TestIP.java +++ b/core/src/test/java/net/tomp2p/peers/TestIP.java @@ -8,6 +8,8 @@ import org.junit.Assert; import org.junit.Test; +import net.tomp2p.utils.Utils; + public class TestIP { @Test public void testMask4() throws UnknownHostException { @@ -51,4 +53,39 @@ public void testMask4Set() throws UnknownHostException { InetAddress inet3 = test.toInetAddress(); Assert.assertEquals(inet2, inet3); } + + @Test + public void testCalc1() throws UnknownHostException { + + IP.IPv4 mask = IP.fromInet4Address(InetAddress.getByName("10.0.0.3")); + mask = mask.maskWithNetworkMask(24); + IP.IPv4 masked = IP.fromInet4Address(InetAddress.getByName("0.0.0.2")); + masked = masked.maskWithNetworkMaskInv(24); + InetAddress i = mask.set(masked).toInetAddress(); + Assert.assertEquals(i, InetAddress.getByName("10.0.0.2") ); + } + + @Test + public void testCalc2() throws UnknownHostException { + + IP.IPv4 mask = IP.fromInet4Address(InetAddress.getByName("10.0.0.3")); + mask = mask.maskWithNetworkMask(16); + IP.IPv4 masked = IP.fromInet4Address(InetAddress.getByName("0.0.1.2")); + masked = masked.maskWithNetworkMaskInv(16); + InetAddress i = mask.set(masked).toInetAddress(); + Assert.assertEquals(i, InetAddress.getByName("10.0.1.2") ); + } + + @Test + public void testCalc3() throws UnknownHostException { + + IP.IPv4 mask = IP.fromInet4Address(InetAddress.getByName("10.0.0.3")); + System.err.println(mask); + mask = mask.maskWithNetworkMask(0); + System.err.println(mask); + IP.IPv4 masked = IP.fromInet4Address(InetAddress.getByName("1.2.3.4")); + masked = masked.maskWithNetworkMaskInv(0); + InetAddress i = mask.set(masked).toInetAddress(); + Assert.assertEquals(i, InetAddress.getByName("1.2.3.4") ); + } } From 3830fdde865aa5a8c3668ce21874fa6d24afda09 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 16 Sep 2015 18:58:49 +0200 Subject: [PATCH 077/135] NAT fixes --- .../main/java/net/tomp2p/holep/HolePRPC.java | 8 +- .../net/tomp2p/relay/BaseRelayClient.java | 70 ---- .../net/tomp2p/relay/BaseRelayServer.java | 271 --------------- .../main/java/net/tomp2p/relay/Forwarder.java | 8 +- .../net/tomp2p/relay/OfflineListener.java | 17 - .../main/java/net/tomp2p/relay/RconRPC.java | 6 +- .../main/java/net/tomp2p/relay/RelayRPC.java | 5 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 3 - .../tomp2p/holep/manual/TestNATStress.java | 323 ++++++++++++++++-- release_instructions.txt | 1 + 10 files changed, 315 insertions(+), 397 deletions(-) delete mode 100644 nat/src/main/java/net/tomp2p/relay/BaseRelayClient.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java delete mode 100644 nat/src/main/java/net/tomp2p/relay/OfflineListener.java diff --git a/nat/src/main/java/net/tomp2p/holep/HolePRPC.java b/nat/src/main/java/net/tomp2p/holep/HolePRPC.java index f6339eb00..f11ac17d9 100644 --- a/nat/src/main/java/net/tomp2p/holep/HolePRPC.java +++ b/nat/src/main/java/net/tomp2p/holep/HolePRPC.java @@ -15,7 +15,7 @@ import net.tomp2p.message.NeighborSet; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.relay.BaseRelayServer; +import net.tomp2p.relay.Forwarder; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; @@ -101,7 +101,7 @@ public void operationComplete(FutureDone future) throws Exception { * @param responder */ private void forwardHolePunchMessage(final Message message, final Responder responder) { - final BaseRelayServer forwarder = extractRelayForwarder(message); + final Forwarder forwarder = extractRelayForwarder(message); if (forwarder != null) { final Message forwardMessage = createForwardPortsMessage(message, forwarder.unreachablePeerAddress()); final FutureDone response = forwarder.forwardToUnreachable(forwardMessage); @@ -175,9 +175,9 @@ private Message createAnswerMessage(final Message originalMessage, final Message * the unreachable peer * @return forwarder */ - private BaseRelayServer extractRelayForwarder(final Message message) { + private Forwarder extractRelayForwarder(final Message message) { final Dispatcher dispatcher = peer.connectionBean().dispatcher(); - return (BaseRelayServer) dispatcher.searchHandler(BaseRelayServer.class, peer.peerID(), message.recipient().peerId()); + return (Forwarder) dispatcher.searchHandler(Forwarder.class, peer.peerID(), message.recipient().peerId()); } /** diff --git a/nat/src/main/java/net/tomp2p/relay/BaseRelayClient.java b/nat/src/main/java/net/tomp2p/relay/BaseRelayClient.java deleted file mode 100644 index 8415b8725..000000000 --- a/nat/src/main/java/net/tomp2p/relay/BaseRelayClient.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.tomp2p.relay; - -import java.util.HashSet; -import java.util.Set; - -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.message.Message; -import net.tomp2p.peers.PeerAddress; - -/** - * Every firewalled peer has one or multiple relay servers. This class represents one of these relays (at the - * client side). - * - * @author Nico Rutishauser - * - */ -public abstract class BaseRelayClient { - - private final PeerAddress relayAddress; - protected final Set listeners; - - public BaseRelayClient(PeerAddress relayAddress) { - this.relayAddress = relayAddress; - this.listeners = new HashSet(); - } - - public PeerAddress relayAddress() { - return relayAddress; - } - - public abstract FutureResponse sendToRelay(Message message); - - public abstract FutureDone shutdown(); - - /** - * Is called when the {@link PeerMapUpdateTask} successfully sent the map - * to the relay peer. - */ - public abstract void onMapUpdateSuccess(); - - /** - * Is called when the {@link PeerMapUpdateTask} failed to send the new map. - * This can act as an indicator that the relay peer is now offline. - */ - public abstract void onMapUpdateFailed(); - - /** - * Adds a close listener for an open peer connection, so that if the - * connection to the relay peer drops, a new relay is found and a new relay - * connection is established - * - * @param peerConnection - * the peer connection on which to add a close listener - * @param bootstrapBuilder - * bootstrap builder, used to find neighbors of this peer - */ - public final void addCloseListener(RelayListener listener) { - listeners.add(listener); - } - - /** - * Call this to notify all listeners attached by {@link BaseRelayClient#addCloseListener(RelayListener)} - */ - protected final void notifyCloseListeners() { - for (RelayListener relayListener : listeners) { - relayListener.relayFailed(relayAddress()); - } - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java b/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java deleted file mode 100644 index e7b320496..000000000 --- a/nat/src/main/java/net/tomp2p/relay/BaseRelayServer.java +++ /dev/null @@ -1,271 +0,0 @@ -package net.tomp2p.relay; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicLong; - -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.PeerException; -import net.tomp2p.connection.Responder; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.message.NeighborSet; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerStatistic; -import net.tomp2p.peers.PeerStatusListener; -import net.tomp2p.peers.RTT; -import net.tomp2p.rpc.DispatchHandler; -import net.tomp2p.rpc.NeighborRPC; -import net.tomp2p.rpc.RPC; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Abstract class that provides the basic functionality to handle relay requests - * at the relay server. It also acts as a dispatcher for different kinds - * of messages. - * - * The RelayForwarder is responsible for forwarding all messages that are - * received on a relay peer, but are intended for an unreachable peer that is - * connected to the relay peer. Every unreachable node has an own instance of - * this class at the relay server. - * - * @author Nico Rutishauser - * @author Raphael Voellmy - * - */ -public abstract class BaseRelayServer extends DispatchHandler implements PeerStatusListener { - - private final static Logger LOG = LoggerFactory.getLogger(BaseRelayServer.class); - - private final Number160 relayPeerId; - private PeerAddress unreachablePeer; - private final ArrayList offlineListeners; - private List> peerMap = null; - private final static AtomicLong messageCounter = new AtomicLong(); - - protected BaseRelayServer(Peer peer, PeerAddress unreachablePeer, RelayType relayType) { - super(peer.peerBean(), peer.connectionBean()); - this.unreachablePeer = unreachablePeer.changeRelayed(true).changeSlow(relayType.isSlow()); - this.relayPeerId = peer.peerID(); - this.offlineListeners = new ArrayList(); - } - - public final PeerAddress unreachablePeerAddress() { - return unreachablePeer; - } - - protected final Number160 unreachablePeerId() { - return unreachablePeer.peerId(); - } - - public void addOfflineListener(OfflineListener listener) { - offlineListeners.add(listener); - } - - protected void notifyOfflineListeners() { - for (OfflineListener listener : offlineListeners) { - listener.onUnreachableOffline(unreachablePeer, this); - } - } - - @Override - public final boolean peerFailed(PeerAddress remotePeer, PeerException exception) { - // not handled here - return false; - } - - @Override - public final boolean peerFound(PeerAddress remotePeer, PeerAddress referrer, PeerConnection peerConnection, - RTT roundTripTime) { - if (referrer == null || remotePeer.equals(referrer)) { - // if firsthand (referrer is null), then full trust. - // if second hand and a stable peerconnection, we can trust as well - - if (remotePeer.peerId().equals(unreachablePeerId()) && remotePeer.isRelayed()) { - // we got new information about this peer, e.g. its active relays - LOG.trace("Update the unreachable peer to {} based on {}, ref {}", unreachablePeerAddress(), remotePeer, - referrer); - this.unreachablePeer = remotePeer; - return true; - } - } - - return false; - } - - public final Number160 relayPeerId() { - return relayPeerId; - } - - /** - * Receive a message at the relay server from a given peer - */ - @Override - public final void handleResponse(Message message, PeerConnection peerConnection, boolean sign, final Responder responder) - throws Exception { - // special treatment for ping and neighbor - if (message.command() == RPC.Commands.PING.getNr()) { - LOG.debug("Received message {} to handle ping for unreachable peer {}", message, unreachablePeer); - handlePing(message, responder); - } else if (message.command() == RPC.Commands.NEIGHBOR.getNr()) { - LOG.debug("Received message {} to handle neighbor request for unreachable peer {}", message, unreachablePeer); - handleNeigbhor(message, responder); - } else { - messageCounter.incrementAndGet(); - LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeer); - FutureDone response = forwardToUnreachable(message); - response.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureDone future) throws Exception { - if (future.isSuccess()) { - Message answerMessage = future.object(); - LOG.debug("Returing from relay to requester: {}", answerMessage); - responder.response(answerMessage); - } else { - responder.failed(Type.DENIED, "Relaying message failed: " + future.failedReason()); - } - } - }); - } - } - - /** - * Forwards a message to the unrachable peer. The implementation should notify the unreachable peer - * and return a response as soon as possible. - * - * @param message the message that is intended for the unreachable peer - * @return the response to the requester - */ - public abstract FutureDone forwardToUnreachable(Message message); - - /** - * When a ping message is received - * - * @param message - * @param responder - */ - private void handlePing(Message message, Responder responder) { - Message response = createResponseMessage(message, isAlive() ? Type.OK : Type.EXCEPTION, unreachablePeerAddress()); - responder.response(response); - } - - /** - * Checks whether the relayed peer is still alive. - * - * @return - */ - protected abstract boolean isAlive(); - - /** - * When a neighbor message is received - * - * @param message - * @param responder - */ - private void handleNeigbhor(final Message message, Responder responder) { - if (message.keyList().size() < 2) { - throw new IllegalArgumentException("We need the location and domain key at least"); - } - if (!(message.type() == Type.REQUEST_1 || message.type() == Type.REQUEST_2 || message.type() == Type.REQUEST_3 || message - .type() == Type.REQUEST_4) && (message.command() == RPC.Commands.NEIGHBOR.getNr())) { - throw new IllegalArgumentException("Message content is wrong"); - } - Number160 locationKey = message.key(0); - - Collection neighbors = getNeighbors(locationKey, NeighborRPC.NEIGHBOR_SIZE); - if (neighbors == null) { - // return empty neighbor set - Message response = createResponseMessage(message, Type.NOT_FOUND, unreachablePeer); - response.neighborsSet(new NeighborSet(-1, Collections. emptyList())); - responder.response(response); - return; - } - - // Create response message and set neighbors - final Message responseMessage = createResponseMessage(message, Type.OK, unreachablePeer); - - // TODO: the relayed peer must be up-to-date here - // neighbors.add(peerConnection.remotePeer()); - - LOG.debug("found the following neighbors {}", neighbors); - - NeighborSet neighborSet = new NeighborSet(NeighborRPC.NEIGHBOR_LIMIT, neighbors); - responseMessage.neighborsSet(neighborSet); - - // we can't do fast get here, as we only send over the neighbors and not the keys stored - responder.response(responseMessage); - } - - private SortedSet getNeighbors(Number160 id, int atLeast) { - LOG.trace("Answering routing request on behalf of unreachable peer {}, neighbors of {}", unreachablePeerAddress(), - id); - if (peerMap == null) { - return null; - } else { - SortedSet closePeers = PeerMap.closePeers(unreachablePeerId(), id, NeighborRPC.NEIGHBOR_SIZE, - peerMap, null); - SortedSet result = new TreeSet(PeerMap.createXORAddressComparator(id)); - for (PeerStatistic p : closePeers) { - result.add(p.peerAddress()); - } - return result; - } - } - - /** - * Returns the current peer map from the mobile device - */ - public final Collection getPeerMap() { - Collection peerAddresses = new ArrayList(); - if (peerMap == null || peerMap.isEmpty()) { - return peerAddresses; - } - - Collection statistics = new ArrayList(); - for (Map map : peerMap) { - statistics.addAll(map.values()); - } - for (PeerStatistic peerStatatistic : statistics) { - peerAddresses.add(peerStatatistic.peerAddress()); - } - return peerAddresses; - } - - /** - * Update the peerMap of the unreachable peer - * - * @param peerMap the extracted peer map - * @param requestMessage the original message that contained the extracted peer map - * @param preparedResponse the response that will be sent to the unreachable peer - */ - public final void setPeerMap(List> peerMap, Message requestMessage, - Message preparedResponse) { - this.peerMap = peerMap; - peerMapUpdated(requestMessage, preparedResponse); - } - - /** - * Is called when the unreachable peer sent an update to the relay peer. This gives the server - * implementation the chance to extract further information from the original map update message or attach - * something to the response. - * - * @param originalMessage the original message that contained the extracted peer map - */ - protected abstract void peerMapUpdated(Message originalMessage, Message preparedResponse); - - public static long messageCounter() { - return messageCounter.get(); - } -} diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 678656e97..5d0d3a334 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -44,7 +44,7 @@ public class Forwarder extends DispatchHandler { private final List buffer = Collections.synchronizedList(new ArrayList()); - private int capacity = 16; + //private int capacity = 16; private long lastAccess = System.currentTimeMillis(); private int bufferTimeSec = 60; @@ -68,7 +68,7 @@ private FutureDone forwardOrBuffer(final Message requestMessage) { - private FutureDone forwardToUnreachable(final Message message) { + public FutureDone forwardToUnreachable(final Message message) { // Send message via direct message through the open connection to the unreachable peer LOG.debug("Sending {} to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_2); @@ -280,5 +280,9 @@ public List buffered() { } buffer.clear(); return retVal; + } + + public PeerAddress unreachablePeerAddress() { + return unreachablePeerConnection.remotePeer(); } } diff --git a/nat/src/main/java/net/tomp2p/relay/OfflineListener.java b/nat/src/main/java/net/tomp2p/relay/OfflineListener.java deleted file mode 100644 index 87ede43f3..000000000 --- a/nat/src/main/java/net/tomp2p/relay/OfflineListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.tomp2p.relay; - -import net.tomp2p.peers.PeerAddress; - -/** - * @author Nico Rutishauser - */ -public interface OfflineListener { - - /** - * Is called when the {@link BaseRelayServer} detects that the unreachable peer is now offline. - * - * @param unreachablePeer the peer that went offline - * @param the server that held the connection to the unreachable peer - */ - void onUnreachableOffline(PeerAddress unreachablePeer, BaseRelayServer server); -} diff --git a/nat/src/main/java/net/tomp2p/relay/RconRPC.java b/nat/src/main/java/net/tomp2p/relay/RconRPC.java index ae1255a57..515512c20 100644 --- a/nat/src/main/java/net/tomp2p/relay/RconRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RconRPC.java @@ -95,7 +95,7 @@ public void handleResponse(final Message message, final PeerConnection peerConne */ private void handleRconForward(final Message message, final Responder responder) throws Exception { // get the relayForwarderRPC via Dispatcher to retrieve the existing peerConnection - final BaseRelayServer forwarder = extractRelayForwarder(message); + final Forwarder forwarder = extractRelayForwarder(message); if (forwarder != null) { final Message forwardMessage = createForwardMessage(message, forwarder.unreachablePeerAddress()); forwarder.handleResponse(forwardMessage, null, true, responder); @@ -112,9 +112,9 @@ private void handleRconForward(final Message message, final Responder responder) * @param unreachablePeerId the unreachable peer * @return forwarder */ - private BaseRelayServer extractRelayForwarder(final Message message) { + private Forwarder extractRelayForwarder(final Message message) { final Dispatcher dispatcher = peer.connectionBean().dispatcher(); - return (BaseRelayServer) dispatcher.searchHandler(BaseRelayServer.class, peer.peerID(), message.recipient().peerId()); + return (Forwarder) dispatcher.searchHandler(Forwarder.class, peer.peerID(), message.recipient().peerId()); } /** diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 4567356aa..28473ad37 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -237,10 +237,11 @@ private void handleSetup(Message message, final PeerConnection unreachablePeerCo psa2.add(peer().peerAddress().peerSocketAddress()); final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer( - unreachablePeerConnectionOrig.remotePeer().changeRelayed(true).changePeerSocketAddresses(psa2)); + unreachablePeerConnectionOrig.remotePeer().changeRelayed(true).changeFirewalledTCP(false).changeFirewalledUDP(false).changePeerSocketAddresses(psa2)); //now we can add this peer to the map, as we have now set the flag - peerBean().notifyPeerFound(message.sender(), message.sender(), unreachablePeerConnectionCopy, null); + //its TCP, we have a connection to this peer, so mark it as first hand + peerBean().notifyPeerFound(unreachablePeerConnectionCopy.remotePeer(), null, unreachablePeerConnectionCopy, null); for (Commands command : RPC.Commands.values()) { if (command == RPC.Commands.RCON) { // We must register the rconRPC for every unreachable peer that diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 80f626a30..bfd9bc523 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -23,7 +23,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.relay.BaseRelayServer; import net.tomp2p.relay.Forwarder; import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; @@ -584,7 +583,6 @@ public Serializable execute() throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2.peerAddress()).object("test").start().awaitUninterruptibly(); Assert.assertEquals("me", fdir1.object()); //should be direct not over relay - Assert.assertEquals(0, BaseRelayServer.messageCounter()); return "done"; } }, new Command() { @@ -643,7 +641,6 @@ public Object reply(PeerAddress sender, Object request) throws Exception { FutureDirect fdir1 = peer1.sendDirect(peer2.peerAddress()).object("test").start().awaitUninterruptibly(); Assert.assertEquals("me", fdir1.object()); //should be direct not over relay - Assert.assertEquals(0, BaseRelayServer.messageCounter()); return "done"; } }, new Command() { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index cd97b8ab0..f66a1ec26 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Random; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.After; import org.junit.Assert; @@ -11,16 +12,21 @@ import org.junit.Test; import net.tomp2p.connection.PeerConnection; +import net.tomp2p.dht.FutureGet; +import net.tomp2p.dht.FuturePut; +import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.RequestP2PConfiguration; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.relay.RelayCallback; +import net.tomp2p.storage.Data; /** * 2 UPNP peers behind same NAT, 1 behind other NAT (total 3 peers) 2 port @@ -38,7 +44,7 @@ public class TestNATStress implements Serializable { static private Number160 relayPeerId1 = new Number160(RND); static private Number160 relayPeerId2 = new Number160(RND); // ### CHANGE THIS TO YOUR INTERFACE### - final static private String INF = "eth1"; + final static private String INF = "enp0s25"; @Before public void before() throws IOException, InterruptedException { @@ -68,6 +74,7 @@ public void after() throws IOException, InterruptedException { @Test public void testStress() throws Exception { Peer relayPeer1 = null; + PeerDHT relayDHT1 = null; Peer relayPeer2 = null; PeerDHT pd = null; @@ -76,6 +83,7 @@ public void testStress() throws Exception { try { relayPeer1 = createRelay(relayPeerId1, 5002); + relayDHT1 = new PeerBuilderDHT(relayPeer1).start(); final Peer relayPeer11 = relayPeer1; relayPeer2 = createRelay(relayPeerId2, 5003); final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); @@ -83,13 +91,36 @@ public void testStress() throws Exception { System.out.println("relay 1:"+relayPeer1.peerAddress()); System.out.println("relay 2:"+relayPeer2.peerAddress()); + + final AtomicBoolean a = new AtomicBoolean(false); + RemotePeerCallback rmc = new RemotePeerCallback() { + + @Override + public void onNull(int i) {} + + @Override + public void onFinished(int i) { + if(i == 2) { + System.err.println("MAP SIZE: "+relayPeer11.peerBean().peerMap().all().size()); + for(PeerAddress pa:relayPeer11.peerBean().peerMap().all()) { + System.err.println("got: "+pa); + } + a.set(relayPeer11.peerBean().peerMap().all().size() == 9); + } + + } + }; - unr[0] = LocalNATUtils.executePeer(0, sync, new Command() { + unr[0] = LocalNATUtils.executePeer(0, rmc, sync, new Command() { @Override public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.0.2", 5000, 0); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); PeerNAT pn = new PeerBuilderNAT(peer1).start(); FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); @@ -98,6 +129,31 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(10000); + return true; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from1")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -108,6 +164,10 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.0.3", 5000, 1); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); PeerNAT pn = new PeerBuilderNAT(peer1).start(); FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); @@ -116,6 +176,31 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from2")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -126,6 +211,10 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.1.2", 5000, 2); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start(); PeerNAT pn = new PeerBuilderNAT(peer1).start(); FutureNAT fn = pn.portForwarding(fd1).awaitUninterruptibly(); @@ -134,6 +223,31 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from3")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -144,12 +258,41 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.2.2", 5000, 3, 4000); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); return fd.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from4")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -160,12 +303,41 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.2.3", 5000, 4, 4001); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); return fd.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from5")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -176,12 +348,41 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.3.2", 5000, 5, 4000); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); return fd.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from6")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -192,6 +393,10 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.4.2", 5000, 6); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -201,12 +406,36 @@ public Serializable execute() throws Exception { //setup relay pn1.startRelay(); cl1.await(); - Thread.sleep(20*1000); return "true"; } }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from7")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -217,6 +446,10 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.4.3", 5000, 7); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -231,6 +464,31 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { + Thread.sleep(5000); + return "true"; + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from8")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; + } + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); return LocalNATUtils.shutdown((Peer)get("p1")); } }); @@ -241,6 +499,10 @@ public Serializable execute() throws Exception { public Serializable execute() throws Exception { Peer peer1 = LocalNATUtils.init("10.0.5.2", 5000, 8); put("p1", peer1); + PeerDHT pdht = new PeerBuilderDHT(peer1).start(); + put("pd", pdht); + PeerNAT pnat = new PeerBuilderNAT(peer1).start(); + put("pn", pnat); FutureDiscover fd1 = peer1.discover().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); Assert.assertFalse(fd1.isDiscoveredTCP()); @@ -255,39 +517,50 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - return LocalNATUtils.shutdown((Peer)get("p1")); + Thread.sleep(5000); + return "true"; } - }); - - new Thread(new Runnable() { - + }, new Command() { @Override - public void run() { - for(;;) { - System.err.println("MAP SIZE: "+relayPeer11.peerBean().peerMap().all().size()); - for(PeerAddress pa:relayPeer11.peerBean().peerMap().all()) { - System.err.println("PA: "+pa); - } - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FuturePut fp = pdht.add(Number160.ONE).data(new Data("from9")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + return fp.isSuccess(); + } + }, new Command() { + @Override + public Serializable execute() throws Exception { + PeerDHT pdht = (PeerDHT)get("pd"); + FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + if(fg.isSuccess()) { + return 9 == fg.dataMap().size() ? true: false; + } else { + return false; } - - } - }).start(); + }, new Command() { + @Override + public Serializable execute() throws Exception { + System.out.println("shutdown"); + return LocalNATUtils.shutdown((Peer)get("p1")); + } + }); + for (RemotePeer u : unr) { u.waitFor(); } + //test if we have 9 peers + Assert.assertTrue(a.get()); + + FutureGet fg = relayDHT1.get(Number160.ONE).all().start().awaitUninterruptibly(); + Assert.assertEquals(9, fg.dataMap().size()); for (RemotePeer u : unr) { - for (int i = 0; i < u.resultSize(); i++) { - Assert.assertEquals("true", u.getResult(i)); + for (int i = 0; i < u.resultSize() - 1; i++) { + Assert.assertEquals("true", u.getResult(i).toString()); } + Assert.assertEquals("shutdown done", u.getResult(u.resultSize() - 1).toString()); } } finally { diff --git a/release_instructions.txt b/release_instructions.txt index e05d17f47..04a221a09 100644 --- a/release_instructions.txt +++ b/release_instructions.txt @@ -29,5 +29,6 @@ mvn deploy:deploy-file \ -Dversion=3.5.x.Patched \ -Dpackaging=jar \ -Dfile=netty-3.5.x.Patched.jar \ + -Dsources=netty-3.5.x.Patched-sources.jar -DrepositoryId=ssh-tomp2p \ -Durl=scp://tomp2p.net/home/##username##/maven From e21d4024b568178a8d731d1ef81bdb756e23306e Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 17 Sep 2015 17:56:25 +0200 Subject: [PATCH 078/135] fixing NAT/stresstest, almost there, few runs work, longer runs result still in failure --- .../connection/DefaultSendBehavior.java | 33 +-- .../net/tomp2p/connection/Dispatcher.java | 28 ++- .../net/tomp2p/connection/PeerCreator.java | 2 +- .../net/tomp2p/connection/RequestHandler.java | 14 +- .../java/net/tomp2p/connection/Sender.java | 221 ++++++++---------- .../net/tomp2p/connection/TimeoutFactory.java | 4 +- .../java/net/tomp2p/futures/BaseFuture.java | 2 + .../net/tomp2p/futures/BaseFutureImpl.java | 7 + .../main/java/net/tomp2p/message/Message.java | 41 +--- .../net/tomp2p/message/TomP2POutbound.java | 3 + .../tomp2p/p2p/builder/BootstrapBuilder.java | 8 + .../src/main/java/net/tomp2p/utils/Utils.java | 9 +- .../tomp2p/holep/manual/LocalNATUtils.java | 46 +++- .../net/tomp2p/holep/manual/RemotePeer.java | 1 - .../java/net/tomp2p/holep/manual/Repeat.java | 12 + .../tomp2p/holep/manual/TestNATStress.java | 107 ++++++--- nat/src/test/resources/logback.xml | 13 +- 17 files changed, 306 insertions(+), 245 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/Repeat.java diff --git a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java index 752fef1e2..10d45f958 100644 --- a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java +++ b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java @@ -1,7 +1,6 @@ package net.tomp2p.connection; import net.tomp2p.message.Message; -import net.tomp2p.rpc.RPC; /** * Default sending behavior for UDP and TCP messages. Depending whether the @@ -22,7 +21,7 @@ public SendMethod tcpSendBehavior(Message message) { return SendMethod.SELF; } - if(message.isReflected()) { + if(message.recipientReflected() != null) { return SendMethod.DIRECT; } @@ -32,11 +31,6 @@ public SendMethod tcpSendBehavior(Message message) { // relayed. Thus send the message to // one of the receiver's relay peers return SendMethod.RELAY; - } else if (message.recipient().isSlow()) { - // the recipient is a slow peer (i.e. a mobile device). Send it - // to the relay such that this - // one can handle latency and buffer multiple requests - return SendMethod.RELAY; } else { // Messages with small size can be sent over relay, other messages should be sent directly (more efficient) if(message.estimateSize() > MTU) { @@ -45,10 +39,9 @@ public SendMethod tcpSendBehavior(Message message) { return SendMethod.RELAY; } } - } else { - // send directly - return SendMethod.DIRECT; } + // send directly + return SendMethod.DIRECT; } @Override @@ -58,22 +51,14 @@ public SendMethod udpSendBehavior(Message message) throws UnsupportedOperationEx return SendMethod.SELF; } - if(message.isReflected()) { + if(message.recipientReflected() != null) { return SendMethod.DIRECT; } - - if (message.recipient().isRelayed() && message.sender().isRelayed() - && !(message.command() == RPC.Commands.NEIGHBOR.getNr() || message.command() == RPC.Commands.PING.getNr())) { - return SendMethod.HOLEP; - } else if (message.recipient().isRelayed()) { - if (message.command() == RPC.Commands.NEIGHBOR.getNr() || message.command() == RPC.Commands.PING.getNr()) { - return SendMethod.RELAY; - } else { - throw new UnsupportedOperationException( - "Tried to send UDP message to unreachable peers. Only TCP messages can be sent to unreachable peers"); - } - } else { - return SendMethod.DIRECT; + + if(message.recipient().isRelayed()) { + return SendMethod.RELAY; } + + return SendMethod.DIRECT; } } diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 1b99dd508..d8f030ba1 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -27,6 +27,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -72,7 +74,7 @@ public class Dispatcher extends SimpleChannelInboundHandler { final private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); final private Lock readLock = reentrantReadWriteLock.readLock(); final private Lock writeLock = reentrantReadWriteLock.writeLock(); - final private Map> ioHandlers = new HashMap>(); + final private SortedMap> ioHandlers = new TreeMap>(); /** * Map that stores requests that are not answered yet. Normally, the {@link RequestHandler} handles @@ -151,6 +153,17 @@ public void removeIoHandler(final Number160 peerId, final Number160 onBehalfOf) writeLock.unlock(); } } + + public void removeIoHandler(final Number160 peerId) { + writeLock.lock(); + try { + Number320 min = new Number320(peerId, Number160.ZERO); + Number320 max = new Number320(peerId, Number160.MAX_VALUE); + ioHandlers.subMap(min, max).clear(); + } finally { + writeLock.unlock(); + } + } @Override protected void channelRead0(final ChannelHandlerContext ctx, final Message message) throws Exception { @@ -320,20 +333,11 @@ public DispatchHandler associatedHandler(final Message message) { return searchHandler(peerId, peerId, message.command()); // else we search for the handler that we are responsible for } else { - DispatchHandler handler = searchHandler(recipient.peerId(), recipient.peerId(), message.command()); + DispatchHandler handler = searchHandler(peerBean().serverPeerAddress().peerId(), recipient.peerId(), message.command()); if (handler != null) { return handler; } - - // If we could not find a handler that we are responsible for, we - // are most likely a relay. Since we have no ID of the relay, we - // just take the first one. - Map map = searchHandler(Integer.valueOf(message.command())); - for (Map.Entry entry : map.entrySet()) { - if (entry.getKey().domainKey().equals(recipient.peerId())) { - return entry.getValue(); - } - } + LOG.warn("No handler found for {} no behalf of {}, command {}", peerBean().serverPeerAddress().peerId(), recipient.peerId(), message.command()); return null; } } diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index 57d103eef..b67d1ce0d 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -137,7 +137,7 @@ public FutureDone shutdown() { LOG.debug("Shutting down..."); } // de-register in dispatcher - connectionBean.dispatcher().removeIoHandler(peerBean().serverPeerAddress().peerId(), peerBean().serverPeerAddress().peerId()); + connectionBean.dispatcher().removeIoHandler(peerBean().serverPeerAddress().peerId()); // shutdown running tasks for this peer if (peerBean.maintenanceTask() != null) { peerBean.maintenanceTask().shutdown(); diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index 9a9723e7a..903268631 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -15,18 +15,17 @@ */ package net.tomp2p.connection; - import io.netty.channel.ChannelHandlerContext; + import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.tomp2p.futures.FutureResponse; import net.tomp2p.message.Message; import net.tomp2p.message.MessageID; -import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerStatusListener; import net.tomp2p.rpc.RPC; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Is able to send TCP and UDP messages (as a request) and processes incoming responses. It is important that * this class handles @@ -294,9 +293,8 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo } //NAT reflection, change it back, as this will be stored in our peer map that may be queried from other peers - if(message.recipientBeforeTranslation() != null) { - PeerAddress realAddress = responseMessage.sender().changePeerSocketAddress(message.recipientBeforeTranslation()); - responseMessage.sender(realAddress); + if(message.recipientReflected() != null) { + responseMessage.sender(message.recipient().changePeerSocketAddress(message.recipient().peerSocketAddress())); } // Stop time measurement of RTT diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index b395f6f3e..dd8669d3c 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -20,14 +20,12 @@ import java.net.InetSocketAddress; import java.nio.channels.ClosedChannelException; import java.util.ArrayList; -import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.CancellationException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReferenceArray; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,8 +40,6 @@ import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.Cancel; import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureForkJoin; -import net.tomp2p.futures.FuturePing; import net.tomp2p.futures.FutureResponse; import net.tomp2p.message.DataFilter; import net.tomp2p.message.DataFilterTTL; @@ -52,7 +48,6 @@ import net.tomp2p.message.TomP2PCumulationTCP; import net.tomp2p.message.TomP2POutbound; import net.tomp2p.message.TomP2PSinglePacketUDP; -import net.tomp2p.p2p.builder.PingBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; @@ -149,14 +144,7 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu } // NAT reflection - rewrite recipient if we found a local address for // the recipient - PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); - if(reflectedRecipient != null) { - PeerSocketAddress orig = message.recipient().peerSocketAddress(); - message.saveOriginalRecipientBeforeTranslation(orig); - message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); - message.reflected(); - LOG.debug("reflect recipient TCP {}", message); - } + handleReflection(message); removePeerIfFailed(futureResponse, message); @@ -209,9 +197,20 @@ private void handleRcon(final SimpleChannelInboundHandler handler, fina final ChannelCreator channelCreator, final int connectTimeoutMillis, final PeerConnection peerConnection, final TimeoutFactory timeoutHandler) { message.keepAlive(true); + + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + if(ps == null) { + futureResponse.failed("no relay provided, but relay indicated RCON"); + return; + } + if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + LOG.debug("Send to self-relay RCON"); + sendSelf(futureResponse, message); + return; + } LOG.debug("initiate reverse connection setup to peer with peerAddress {}", message.recipient()); - Message rconMessage = createRconMessage(message); + Message rconMessage = createRconMessage(ps, message); final FutureResponse rconResponse = new FutureResponse(rconMessage); // cache the original message until the connection is established @@ -246,9 +245,9 @@ protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Excep * @param message * @return rconMessage */ - private static Message createRconMessage(final Message message) { + private static Message createRconMessage(PeerSocketAddress ps, final Message message) { // get Relay InetAddress from unreachable peer - PeerSocketAddress socketAddress = Utils.extractRandomRelay(message); + // we need to make a copy of the original message Message rconMessage = new Message(); @@ -262,7 +261,7 @@ private static Message createRconMessage(final Message message) { // peer will close the PeerConnection to the unreachable peer. rconMessage.keepAlive(true); // making the message ready to send - readyToSend(message, socketAddress, rconMessage, RPC.Commands.RCON.getNr(), Message.Type.REQUEST_1); + readyToSend(message, ps, rconMessage, RPC.Commands.RCON.getNr(), Message.Type.REQUEST_1); return rconMessage; } @@ -302,7 +301,13 @@ private static void readyToSend(final Message originalMessage, PeerSocketAddress private void connectAndSend(final SimpleChannelInboundHandler handler, final FutureResponse futureResponse, final ChannelCreator channelCreator, final int connectTimeoutMillis, final PeerConnection peerConnection, final TimeoutFactory timeoutHandler, final Message message) { - InetSocketAddress recipient = message.recipient().createSocketTCP(); + final InetSocketAddress recipient; + if(message.recipientReflected() != null) { + recipient = message.recipientReflected().createSocketTCP(); + } else { + recipient = message.recipient().createSocketTCP(); + } + final ChannelFuture channelFuture = sendTCPCreateChannel(recipient, channelCreator, peerConnection, handler, timeoutHandler, connectTimeoutMillis, futureResponse); afterConnect(futureResponse, message, channelFuture, handler == null); @@ -324,81 +329,20 @@ private void connectAndSend(final SimpleChannelInboundHandler handler, private void handleRelay(final SimpleChannelInboundHandler handler, final FutureResponse futureResponse, final Message message, final ChannelCreator channelCreator, final int idleTCPMillis, final int connectTimeoutMillis, final PeerConnection peerConnection, final TimeoutFactory timeoutHandler) { - FutureDone futurePing = pingFirst(message.recipient().peerSocketAddresses()); - futurePing.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(final FutureDone futureDone) throws Exception { - if (futureDone.isSuccess()) { - InetSocketAddress recipient = PeerSocketAddress.createSocketTCP(futureDone.object()); - ChannelFuture channelFuture = sendTCPCreateChannel(recipient, channelCreator, peerConnection, handler, timeoutHandler, - connectTimeoutMillis, futureResponse); - afterConnect(futureResponse, message, channelFuture, handler == null); - - futureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if (future.isFailed()) { - if (future.responseMessage() != null && future.responseMessage().type() != Message.Type.DENIED) { - // remove the failed relay and try again - clearInactivePeerSocketAddress(futureDone); - sendTCP(handler, futureResponse, message, channelCreator, idleTCPMillis, connectTimeoutMillis, - peerConnection); - } - } - } - - private void clearInactivePeerSocketAddress(final FutureDone futureDone) { - Collection tmp = new ArrayList(); - for (PeerSocketAddress psa : message.recipient().peerSocketAddresses()) { - if (psa != null) { - if (!psa.equals(futureDone.object())) { - tmp.add(psa); - } - } - } - message.peerSocketAddresses(tmp); - } - }); - - } else { - futureResponse.failed("No relay could be contacted.", futureDone); - } - } - }); - } - - /** - * Ping all relays of the receiver. The first one answering is picked as the - * responsible relay for this message. - * - * @param peerSocketAddresses - * a collection of relay addresses - * @return - */ - private FutureDone pingFirst(Collection peerSocketAddresses) { - final FutureDone futureDone = new FutureDone(); - - FuturePing[] forks = new FuturePing[peerSocketAddresses.size()]; - int index = 0; - for (PeerSocketAddress psa : peerSocketAddresses) { - if (psa != null) { - InetSocketAddress inetSocketAddress = PeerSocketAddress.createSocketUDP(psa); - PingBuilder pingBuilder = pingBuilderFactory.create(); - forks[index++] = pingBuilder.inetAddress(inetSocketAddress.getAddress()).port(inetSocketAddress.getPort()).start(); - } + + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + if(ps == null) { + futureResponse.failed("no relay provided, but relay indicated TCP"); + return; } - FutureForkJoin ffk = new FutureForkJoin(1, true, new AtomicReferenceArray(forks)); - ffk.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureForkJoin future) throws Exception { - if (future.isSuccess()) { - futureDone.done(future.first().remotePeer().peerSocketAddress()); - } else { - futureDone.failed(future); - } - } - }); - return futureDone; + if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + LOG.debug("Send to self-relay TCP"); + sendSelf(futureResponse, message); + return; + } + InetSocketAddress recipient = PeerSocketAddress.createSocketTCP(ps); + ChannelFuture channelFuture = sendTCPCreateChannel(recipient, channelCreator, peerConnection, handler, timeoutHandler, connectTimeoutMillis, futureResponse); + afterConnect(futureResponse, message, channelFuture, handler == null); } /** @@ -572,14 +516,7 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu // NAT reflection - rewrite recipient if we found a local address for // the recipient - PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); - if(reflectedRecipient != null) { - PeerSocketAddress orig = message.recipient().peerSocketAddress(); - message.saveOriginalRecipientBeforeTranslation(orig); - message.recipient(message.recipient().changePeerSocketAddress(reflectedRecipient)); - message.reflected(); - LOG.debug("reflect recipient UDP {}", message); - } + handleReflection(message); removePeerIfFailed(futureResponse, message); @@ -611,18 +548,24 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu } else { LOG.debug("No hole punching possible, because There is no PeerNAT. New Attempt with Relaying"); } + break; case RELAY: - try { - channelFuture = prepareRelaySendUDP(futureResponse, message, channelCreator, broadcast, handlers, channelFuture); - } catch (Exception e) { - e.printStackTrace(); + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + if(ps == null) { + futureResponse.failed("no relay provided, but relay indicated UDP"); + return; + } + if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + LOG.debug("Send to self-relay UDP, {}", message); + sendSelf(futureResponse, message); return; } + channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); break; case SELF: + LOG.debug("Send to self"); sendSelf(futureResponse, message); - channelFuture = null; - break; + return; default: throw new IllegalArgumentException("UDP messages are not allowed to send over RCON"); } @@ -634,6 +577,14 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu } } + private void handleReflection(final Message message) { + PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); + if(reflectedRecipient != null) { + message.recipientReflected(message.recipient().changePeerSocketAddress(reflectedRecipient)); + LOG.debug("reflect recipient UDP {}", message); + } + } + /** * This method needed to be extracted from sendUDP(...), because it is also * needed by the method handleHolePunch(...). @@ -647,21 +598,31 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu * @return * @throws Exception */ - private ChannelFuture prepareRelaySendUDP(final FutureResponse futureResponse, final Message message, - final ChannelCreator channelCreator, final boolean broadcast, - final Map> handlers, ChannelFuture channelFuture) throws Exception { + private PeerSocketAddress prepareRelaySend(final Message message, final PeerSocketAddress preferredAddress) { List psa = new ArrayList(message.recipient().peerSocketAddresses()); - LOG.debug("send neighbor request to random relay peer {}", psa); if (psa.size() > 0) { - PeerSocketAddress ps = psa.get(random.nextInt(psa.size())); - message.recipientRelay(message.recipient().changePeerSocketAddress(ps).changeRelayed(true)); - channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); + if(psa.contains(preferredAddress)) { + LOG.debug("send neighbor request to preferred relay peer {} out of {}", preferredAddress, psa); + return preferredAddress; + } + + //check for any reflected addresses. Those are *not* preferred. Although they may be more efficient, + //we don't have any internal address information in peersocketaddress -> TODO + while(!psa.isEmpty()) { + PeerSocketAddress ps = psa.remove(random.nextInt(psa.size())); + if(ps.inetAddress().equals(peerBean.serverPeerAddress().peerSocketAddress().inetAddress())) { + continue; + } + message.recipientRelay(message.recipient().changePeerSocketAddress(ps).changeRelayed(true)); + LOG.debug("send neighbor request to random relay peer {} out of {}", ps, psa); + return ps; + } + LOG.error("no non-reflected relays found"); + return null; } else { - String failMessage = "Peer is relayed, but no relay given"; - futureResponse.failed(failMessage); - throw new Exception(failMessage); + LOG.error("Peer is relayed, but no relay given"); + return null; } - return channelFuture; } private FutureDone handleHolePunch(final FutureResponse futureResponse, final Message message, @@ -695,13 +656,19 @@ public void exceptionCaught(Throwable t) throws Exception { private void doRelayFallback(final FutureResponse futureResponse, final Message message, final boolean broadcast, final Map> handlers, ChannelFuture channelFuture) { - try { - channelFuture = prepareRelaySendUDP(futureResponse, message, channelCreator, broadcast, handlers, channelFuture); - afterConnect(futureResponse, message, channelFuture, handler == null); - } catch (Exception e) { - e.printStackTrace(); + + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + if(ps == null) { + futureResponse.failed("no relay provided, but relay indicated HP"); return; } + if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + LOG.debug("Send to self-relay HP"); + sendSelf(futureResponse, message); + return; + } + channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); + afterConnect(futureResponse, message, channelFuture, handler == null); } }); return fDone; @@ -892,10 +859,12 @@ public void operationComplete(FutureResponse future) throws Exception { } else if (message.command() == RPC.Commands.HOLEP.getNr() && message.type().ordinal() == Message.Type.REQUEST_3.ordinal()) { //do nothing, because such a (dummy) message will never reach its target the first time } - LOG.debug("peer failed: {}", message); - synchronized (peerStatusListeners) { - for (PeerStatusListener peerStatusListener : peerStatusListeners) { - peerStatusListener.peerFailed(message.recipient(), new PeerException(future)); + if(!future.isCanceled()) { + LOG.debug("peer failed: {}", message); + synchronized (peerStatusListeners) { + for (PeerStatusListener peerStatusListener : peerStatusListeners) { + peerStatusListener.peerFailed(message.recipient(), new PeerException(future)); + } } } } diff --git a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java index bc13fc662..b2c136910 100644 --- a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java +++ b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java @@ -120,10 +120,9 @@ public TimeHandler(final FutureResponse futureResponse, final List() { @Override public void operationComplete(final ChannelFuture future) throws Exception { @@ -133,6 +132,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { recipient = futureResponse.request().recipient(); } else { + LOG.warn("Channel timeout for channel {} {}.", name, ctx.channel()); ctx.close(); // check if we have set an attribute at least (if we have // already decoded the header) diff --git a/core/src/main/java/net/tomp2p/futures/BaseFuture.java b/core/src/main/java/net/tomp2p/futures/BaseFuture.java index f94ae62d7..c3d1f3450 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFuture.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFuture.java @@ -206,4 +206,6 @@ public enum FutureType { * @return this */ BaseFuture setCancel(Cancel cancel); + + boolean isCanceled(); } diff --git a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java index fa591d718..2fb8fe13c 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java @@ -186,6 +186,13 @@ public boolean isFailed() { return completed && (type != FutureType.OK); } } + + @Override + public boolean isCanceled() { + synchronized (lock) { + return completed && (type == FutureType.CANCEL); + } + } @Override public K failed(final BaseFuture origin) { diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index ddd0d113f..ac5fda1fc 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -166,7 +166,6 @@ public enum Type { private byte command; private PeerAddress sender; private PeerAddress recipient; - private transient PeerAddress recipientRelay; private int options = 0; // Payload: @@ -203,8 +202,8 @@ public enum Type { private transient boolean content = false; private transient boolean verified = false; private transient boolean sendSelf = false; - private transient PeerSocketAddress recipientBeforeTranslation = null; - private transient boolean reflected; + private transient PeerAddress recipientRelay; + private transient PeerAddress recipientReflected; /** * Creates message with a random ID. @@ -346,8 +345,16 @@ public PeerAddress recipientRelay() { public Message recipientRelay(PeerAddress recipientRelay) { this.recipientRelay = recipientRelay; - return this; - + return this; + } + + public PeerAddress recipientReflected() { + return recipientReflected; + } + + public Message recipientReflected(PeerAddress recipientReflected) { + this.recipientReflected = recipientReflected; + return this; } /** @@ -1288,28 +1295,4 @@ public void release() { } } - - public Message saveOriginalRecipientBeforeTranslation(PeerSocketAddress recipientBeforeTranslation) { - this.recipientBeforeTranslation = recipientBeforeTranslation; - return this; - } - - public PeerSocketAddress recipientBeforeTranslation() { - return recipientBeforeTranslation; - } - - public Message reflected(boolean reflected) { - this.reflected = reflected; - return this; - } - - public Message reflected() { - return reflected(true); - } - - public boolean isReflected() { - return reflected; - } - - } diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index 8156a9873..d2755d782 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -56,6 +56,9 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann if(message.recipientRelay()!=null) { //in case of sending to a relay (the relayed flag is already set) recipient = message.recipientRelay().createSocketUDP(); + } else if(message.recipientReflected()!=null) { + //in case we use nat reflection + recipient = message.recipientReflected().createSocketUDP(); } else { recipient = message.recipient().createSocketUDP(); } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java index 14086dceb..72f47b6cb 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java @@ -33,6 +33,7 @@ import net.tomp2p.p2p.RoutingConfiguration; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; @@ -120,6 +121,13 @@ public BootstrapBuilder inetSocketAddress(InetSocketAddress socket) { this.portUDP = socket.getPort(); return this; } + + public BootstrapBuilder peerSocketAddress(PeerSocketAddress socket) { + this.inetAddress = socket.inetAddress(); + this.portTCP = socket.tcpPort(); + this.portUDP = socket.udpPort(); + return this; + } public int portUDP() { return portUDP; diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index de7c57312..631dbf7b9 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -924,11 +924,16 @@ public static int randomPositiveInt(int upperBound) { } return randomInt; } + + public static boolean canReflect(PeerAddress recipient, PeerAddress self) { + return recipient.inetAddress().equals(self.inetAddress()) + && self.internalPeerSocketAddress() != null + && recipient.internalPeerSocketAddress()!=null; + } public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress self) { - //check for NAT reflection - if(recipient.inetAddress().equals(self.inetAddress()) && self.internalPeerSocketAddress() != null && recipient.internalPeerSocketAddress()!=null) { + if(canReflect(recipient, self)) { //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 18f116725..9f57f5496 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -82,7 +82,8 @@ public static RemotePeer executePeer(Class klass, int nr, final CommandSync s public static RemotePeer executePeer(Class klass, final int nr, final RemotePeerCallback remoteCallback, final CommandSync sync, final Command... cmd) throws IOException, InterruptedException, ClassNotFoundException { - sync.init(cmd.length); + final int cmdLen = cmdLen(cmd); + sync.init(cmdLen); String javaHome = System.getProperty("java.home"); String javaBin = javaHome + File.separator + "bin" + File.separator @@ -90,7 +91,7 @@ public static RemotePeer executePeer(Class klass, final int nr, final RemoteP String classpath = System.getProperty("java.class.path"); String className = klass.getCanonicalName(); - final String[] cmds = new String[cmd.length + 10]; + final String[] cmds = new String[cmdLen + 10]; cmds[0] = "sudo"; cmds[1] = "ip"; cmds[2] = "netns"; @@ -101,22 +102,27 @@ public static RemotePeer executePeer(Class klass, final int nr, final RemoteP cmds[7] = classpath; cmds[8] = className; cmds[9] = ""+nr; - for (int i = 10; i < cmds.length; i++) { - cmds[i] = toString(cmd[i - 10]); + int current = 0; + for (int i = 10; i < cmds.length;) { + final int repeat = repeat(cmd[current]); + for(int j=0;j results = new AtomicReferenceArray(cmd.length); + final CountDownLatch cl = new CountDownLatch(cmdLen); + final AtomicReferenceArray results = new AtomicReferenceArray(cmdLen); new Thread(new Runnable() { @Override public void run() { try { InputStreamReader isr = new InputStreamReader(process.getInputStream()); BufferedReader br = new BufferedReader(isr); - for (int i = 0; i < cmd.length; i++) { + for (int i = 0; i < cmdLen; i++) { boolean done = false; while (!done) { @@ -136,7 +142,6 @@ public void run() { } } else { System.out.println("OUT["+nr+"]>null"); - cl.countDown(); remoteCallback.onNull(i); break; } @@ -155,6 +160,31 @@ public void run() { return new RemotePeer(process, cl, cmd, results); } + private static int cmdLen(Command[] cmd) { + int total = 0; + for(Command c:cmd) { + total += repeat(c); + } + return total; + } + + private static int repeat(Command command) { + Repeat repeat; + try { + repeat = command.getClass().getMethod("execute").getAnnotation(Repeat.class); + if(repeat == null) { + return 1; + } + return repeat.repeat(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return 1; + } catch (SecurityException e) { + e.printStackTrace(); + return 1; + } + } + public static int killPeer(Process process) throws InterruptedException, IOException { process.getErrorStream().close(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java index 80bc4d4de..58d863501 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/RemotePeer.java @@ -35,5 +35,4 @@ public Command getCmd(int i) { public int resultSize() { return results.length(); } - } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/Repeat.java b/nat/src/test/java/net/tomp2p/holep/manual/Repeat.java new file mode 100644 index 000000000..ff232541f --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/Repeat.java @@ -0,0 +1,12 @@ +package net.tomp2p.holep.manual; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention( RetentionPolicy.RUNTIME ) // the annotation will be available during runtime +@Target( ElementType.METHOD ) // this can just used in methods +public @interface Repeat { + int repeat() default 1; +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index f66a1ec26..cad6181fc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -16,6 +16,8 @@ import net.tomp2p.dht.FuturePut; import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; import net.tomp2p.nat.PeerBuilderNAT; @@ -45,6 +47,7 @@ public class TestNATStress implements Serializable { static private Number160 relayPeerId2 = new Number160(RND); // ### CHANGE THIS TO YOUR INTERFACE### final static private String INF = "enp0s25"; + final static private int REPEAT = 10; @Before public void before() throws IOException, InterruptedException { @@ -129,24 +132,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(10000); - return true; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from1")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("1 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("1 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("1 get: false"); return false; } } @@ -176,24 +184,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from2")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("2 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("2 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("2 get: false"); return false; } } @@ -223,24 +236,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from3")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("3 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("3 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("3 get: false"); return false; } } @@ -268,24 +286,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from4")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("4 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("4 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("4 get: false"); return false; } } @@ -313,24 +336,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from5")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("5 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("5 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("5 get: false"); return false; } } @@ -358,24 +386,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from6")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("6 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("6 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("6 get: false"); return false; } } @@ -411,24 +444,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from7")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("7 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("7 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("7 get: false"); return false; } } @@ -464,24 +502,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from8")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("8 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("8 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("8 get: false"); return false; } } @@ -517,24 +560,29 @@ public Serializable execute() throws Exception { }, new Command() { @Override public Serializable execute() throws Exception { - Thread.sleep(5000); - return "true"; + BaseFuture fs = ((Peer)get("p1")).bootstrap().peerSocketAddress(relayAddress1).start().awaitUninterruptibly(); + Thread.sleep(2000); + return fs.isSuccess(); } }, new Command() { @Override public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); FuturePut fp = pdht.add(Number160.ONE).data(new Data("from9")).requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); + System.out.println("9 add: " + fp.isSuccess()); return fp.isSuccess(); } }, new Command() { @Override + @Repeat(repeat = REPEAT) public Serializable execute() throws Exception { PeerDHT pdht = (PeerDHT)get("pd"); - FutureGet fg = pdht.get(Number160.ONE).all().start().awaitUninterruptibly(); + FutureGet fg = pdht.get(Number160.ONE).all().requestP2PConfiguration(new RequestP2PConfiguration(10, 0, 0)).start().awaitUninterruptibly(); if(fg.isSuccess()) { + System.out.println("9 get: " + fg.dataMap().size()); return 9 == fg.dataMap().size() ? true: false; } else { + System.out.println("9 get: false"); return false; } } @@ -549,12 +597,13 @@ public Serializable execute() throws Exception { for (RemotePeer u : unr) { u.waitFor(); + System.out.println("done: "+u); } //test if we have 9 peers Assert.assertTrue(a.get()); - FutureGet fg = relayDHT1.get(Number160.ONE).all().start().awaitUninterruptibly(); - Assert.assertEquals(9, fg.dataMap().size()); + //TODO: relay peer is alive, why is a get never terminating? + //TODO: sometimes only 8 results are found. figure out why for (RemotePeer u : unr) { for (int i = 0; i < u.resultSize() - 1; i++) { diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index 1ed25b700..43bf89d08 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -44,7 +44,12 @@ --> + + + + + @@ -53,14 +58,16 @@ - - + + + + - + From 3644e72e3742fd08a3f256b30e799a4bfe14e2b8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 17 Sep 2015 18:04:12 +0200 Subject: [PATCH 079/135] removed unneeded code --- core/src/main/java/net/tomp2p/connection/Sender.java | 4 ---- nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index dd8669d3c..f697a3116 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -520,10 +520,6 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu removePeerIfFailed(futureResponse, message); - if (message.sender().isRelayed()) { - message.peerSocketAddresses(message.sender().peerSocketAddresses()); - } - boolean isFireAndForget = handler == null; final Map> handlers = configureHandlers(handler, futureResponse, idleUDPMillis, diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index cad6181fc..6ec9aca57 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -47,7 +47,7 @@ public class TestNATStress implements Serializable { static private Number160 relayPeerId2 = new Number160(RND); // ### CHANGE THIS TO YOUR INTERFACE### final static private String INF = "enp0s25"; - final static private int REPEAT = 10; + final static private int REPEAT = 20; @Before public void before() throws IOException, InterruptedException { From 62c5ef1529ddb3e09459f9a1f31e45078c35718b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Sun, 4 Oct 2015 18:28:29 +0200 Subject: [PATCH 080/135] fixing testcases, increase receive buffer size for UDP --- .../net/tomp2p/connection/ChannelCreator.java | 12 +- .../net/tomp2p/connection/ChannelServer.java | 4 +- .../net/tomp2p/connection/Dispatcher.java | 11 +- .../java/net/tomp2p/connection/Sender.java | 8 +- .../tomp2p/connection/TestReservation.java | 2 +- .../holep/strategy/AbstractHolePStrategy.java | 1304 ++++++++--------- pom.xml | 2 +- 7 files changed, 680 insertions(+), 663 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java index 2ea7f4bab..df7679bdc 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java @@ -133,7 +133,7 @@ public class ChannelCreator { * @return The channel future object or null if we are shut down */ public ChannelFuture createUDP(final boolean broadcast, final Map> channelHandlers, - FutureResponse futureResponse) { + FutureResponse futureResponse, boolean fireandforget) { readUDP.lock(); try { if (shutdownUDP) { @@ -148,6 +148,10 @@ public ChannelFuture createUDP(final boolean broadcast, final Map() { @Override protected void initChannel(final Channel ch) throws Exception { diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index d8f030ba1..372d83519 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -333,11 +333,18 @@ public DispatchHandler associatedHandler(final Message message) { return searchHandler(peerId, peerId, message.command()); // else we search for the handler that we are responsible for } else { - DispatchHandler handler = searchHandler(peerBean().serverPeerAddress().peerId(), recipient.peerId(), message.command()); + //search first for main peer and port sharing peers + DispatchHandler handler = searchHandler(recipient.peerId(), recipient.peerId(), message.command()); if (handler != null) { return handler; } - LOG.warn("No handler found for {} no behalf of {}, command {}", peerBean().serverPeerAddress().peerId(), recipient.peerId(), message.command()); + + //on behalf on peers + handler = searchHandler(peerBean().serverPeerAddress().peerId(), recipient.peerId(), message.command()); + if (handler != null) { + return handler; + } + LOG.warn("No handler found for {} on behalf of {}, command {}. Message is {}", peerBean().serverPeerAddress().peerId(), recipient.peerId(), RPC.Commands.find(message.command()), message); return null; } } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index f697a3116..f8b53feaf 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -532,7 +532,7 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu ChannelFuture channelFuture = null; switch (sendBehavior.udpSendBehavior(message)) { case DIRECT: - channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); + channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse, isFireAndForget); break; case HOLEP: if (peerBean.holePunchInitiator() != null) { @@ -556,7 +556,7 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu sendSelf(futureResponse, message); return; } - channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); + channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse, isFireAndForget); break; case SELF: LOG.debug("Send to self"); @@ -663,7 +663,7 @@ private void doRelayFallback(final FutureResponse futureResponse, final Message sendSelf(futureResponse, message); return; } - channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse); + channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse, false); afterConnect(futureResponse, message, channelFuture, handler == null); } }); @@ -790,7 +790,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { if (fireAndForget) { futureResponse.responseLater(null); LOG.debug("fire and forget, close channel {} now. {}", futureResponse.request(), future.channel()); - reportMessage(futureResponse, future.channel().close()); + futureResponse.responseNow(); } } }); diff --git a/core/src/test/java/net/tomp2p/connection/TestReservation.java b/core/src/test/java/net/tomp2p/connection/TestReservation.java index 719cd80a7..210b56a88 100644 --- a/core/src/test/java/net/tomp2p/connection/TestReservation.java +++ b/core/src/test/java/net/tomp2p/connection/TestReservation.java @@ -195,7 +195,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio for (int k = 0; k < conn; k++) { ChannelFuture channelFuture = cc.createUDP(false, new HashMap>() { - }, new FutureResponse(null)); + }, new FutureResponse(null), false); channelFuture.addListener(new GenericFutureListener() { @Override public void operationComplete(final ChannelFuture future) throws Exception { diff --git a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java index 41404f662..358ee15f2 100644 --- a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java +++ b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java @@ -1,652 +1,652 @@ -package net.tomp2p.holep.strategy; - -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.util.concurrent.EventExecutorGroup; -import io.netty.util.concurrent.GenericFutureListener; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import net.tomp2p.connection.Dispatcher; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.FutureChannelCreator; -import net.tomp2p.futures.FutureDone; -import net.tomp2p.futures.FutureResponse; -import net.tomp2p.holep.DuplicatesHandler; -import net.tomp2p.holep.HolePInitiatorImpl; -import net.tomp2p.holep.HolePScheduler; -import net.tomp2p.holep.NATType; -import net.tomp2p.message.Buffer; -import net.tomp2p.message.Message; -import net.tomp2p.message.Message.Type; -import net.tomp2p.p2p.Peer; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; -import net.tomp2p.rpc.RPC; -import net.tomp2p.rpc.RPC.Commands; -import net.tomp2p.utils.Pair; -import net.tomp2p.utils.Utils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * DO NOT INSTANCIATE THIS CLASS!
- *
- * - * If you need to add a new supported nat type please extend this class and - * change also {@link NATType} and {@link NATTypeDetection}.
- *
- * - * This class is responsible for the whole hole punching procedure. It covers - * all aspects of the procedure on the sender and the recipient side. - * - * - * @author Jonas Wagner - * - */ -public abstract class AbstractHolePStrategy implements HolePStrategy { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractHolePStrategy.class); - private final int numberOfHoles; - private final int idleUDPSeconds; - private List futureResponses = new ArrayList(); - private PeerAddress originalSender; - protected final Peer peer; - protected final Message originalMessage; - protected volatile List channelFutures = new ArrayList(); - protected volatile List> portMappings = new ArrayList>(); - - /** - * This constructor should never be called by the user, since it should be - * called by its strategy pattern instances like - * {@link PortPreservingStrategy}. - * - * @param peer - * @param numberOfHoles - * @param idleUDPSeconds - * @param originalMessage - */ - protected AbstractHolePStrategy(final Peer peer, final int numberOfHoles, final int idleUDPSeconds, final Message originalMessage) { - this.peer = peer; - this.numberOfHoles = numberOfHoles; - this.idleUDPSeconds = idleUDPSeconds; - this.originalMessage = originalMessage; - LOG.trace("new HolePuncher created, originalMessage {}", originalMessage.toString()); - } - - /** - * This method cares about which socket contacts which socket on the NATs - * which are needed to be traversed. - * - * @param replyMessageFuture2 - * @param replyMessage - */ - protected abstract void doPortGuessingTargetPeer(final Message replyMessage, final FutureDone replyMessageFuture2) - throws Exception; - - /** - * This method needs to be overwritten by each strategy in order to let the - * other peer know which ports it need to contact. - * - * @param holePMessage - * @param initMessageFutureDone - * @param channelFutures2 - */ - protected abstract void doPortGuessingInitiatingPeer(final Message holePMessage, final FutureDone initMessageFutureDone, - final List channelFutures2) throws Exception; - - /** - * This method does two things. If the initiating peer calls it, he gets - * back a {@link List} of new {@link SimpleInboundHandler} to deal with the - * replies of the replying peer. If a replying peer is calling this method - * it will return a {@link List} of default {@link SimpleInboundHandler}s - * from the {@link Dispatcher}. - * - * @param futureResponse - * @return handlerList - */ - protected List>> prepareHandlers(final boolean initiator, - final FutureDone futureDone) { - final List>> handlerList = new ArrayList>>( - numberOfHoles); - SimpleChannelInboundHandler inboundHandler; - Map> handlers; - - if (initiator) { - for (int i = 0; i < numberOfHoles; i++) { - // we need an own futureresponse for every hole we try to punch - futureResponses.add(new FutureResponse(originalMessage)); - inboundHandler = createAfterHolePHandler(futureDone); - handlers = peer.connectionBean().sender().configureHandlers(inboundHandler, futureResponses.get(i), idleUDPSeconds, false); - handlerList.add(handlers); - } - } else { - inboundHandler = new DuplicatesHandler(peer.connectionBean().dispatcher()); - for (int i = 0; i < numberOfHoles; i++) { - // we need an own futureresponse for every hole we try to punch - futureResponses.add(new FutureResponse(originalMessage)); - handlers = peer.connectionBean().sender().configureHandlers(inboundHandler, futureResponses.get(i), idleUDPSeconds, false); - handlerList.add(handlers); - } - } - - return handlerList; - } - - /** - * This is a generic method which creates a number of {@link ChannelFuture}s - * and calls the associated {@link FutureDone} as soon as they're done. - * - * @param futureResponse - * @param handlersList - * @return fDoneChannelFutures - */ - protected FutureDone> createChannelFutures( - final List>> handlersList, final FutureDone mainFutureDone, - final int numberOfHoles) { - - final FutureDone> fDoneChannelFutures = new FutureDone>(); - final AtomicInteger countDown = new AtomicInteger(numberOfHoles); - final List channelFutures = new ArrayList(); - - for (int i = 0; i < numberOfHoles; i++) { - final FutureResponse futureResponse = futureResponses.get(i); - final Map> handlers = handlersList.get(i); - final FutureChannelCreator fcc = peer.connectionBean().reservation().create(1, 0); - Utils.addReleaseListener(fcc, futureResponse); - fcc.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureChannelCreator future) throws Exception { - if (future.isSuccess()) { - final ChannelFuture cF = future.channelCreator().createUDP(BROADCAST_VALUE, handlers, futureResponse); - cF.addListener(new GenericFutureListener() { - @Override - public void operationComplete(final ChannelFuture future) throws Exception { - if (future.isSuccess()) { - channelFutures.add(future); - } else { - mainFutureDone.failed("Error while creating the ChannelFutures!"); - } - countDown.decrementAndGet(); - if (countDown.get() == 0) { - fDoneChannelFutures.done(channelFutures); - } - } - }); - } else { - countDown.decrementAndGet(); - mainFutureDone.failed("Error while creating the ChannelFutures!"); - } - } - }); - } - return fDoneChannelFutures; - } - - /** - * This method initiates the hole punch procedure. - * - * @param mainFutureDone - * @param originalChannelCreator - * @param originalFutureResponse - * @param natType - * @return mainFutureDone A FutureDone which if successful contains - * the response Message from the peer we want to contact - */ - public FutureDone initiateHolePunch(final FutureDone mainFutureDone, final FutureResponse originalFutureResponse) { - //check if testCase == true - if (((HolePInitiatorImpl) peer.peerBean().holePunchInitiator()).isTestCase()) { - mainFutureDone.failed("Gandalf says: You shall not pass!!!"); - return mainFutureDone; - } - final FutureDone> fDoneChannelFutures = createChannelFutures(prepareHandlers(true, mainFutureDone), - mainFutureDone, numberOfHoles); - fDoneChannelFutures.addListener(new BaseFutureAdapter>>() { - @Override - public void operationComplete(final FutureDone> future) throws Exception { - if (future.isSuccess()) { - final List futures = future.object(); - final FutureDone initMessage = createInitMessage(futures); - initMessage.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(final FutureDone future) throws Exception { - if (future.isSuccess()) { - final Message initMessage = future.object(); - sendHolePInitMessage(mainFutureDone, originalFutureResponse, futures, initMessage); - } else { - mainFutureDone.failed("The creation of the initMessage failed!"); - } - } - }); - } else { - mainFutureDone.failed("No ChannelFuture could be created!"); - } - } - }); - return mainFutureDone; - } - - /** - * This method initiates the hole punch procedure on the target peer side. - * - * @return - */ - public FutureDone replyHolePunch() { - originalSender = (PeerAddress) originalMessage.neighborsSetList().get(0).neighbors().toArray()[0]; - final FutureDone replyMessageFuture = new FutureDone(); - final HolePStrategy thisInstance = this; - final FutureDone> rmfChannelFutures = createChannelFutures(prepareHandlers(false, replyMessageFuture), - replyMessageFuture, numberOfHoles); - rmfChannelFutures.addListener(new BaseFutureAdapter>>() { - @Override - public void operationComplete(final FutureDone> future) throws Exception { - if (future.isSuccess()) { - channelFutures = future.object(); - final FutureDone replyMessageFuture2 = createReplyMessage(); - replyMessageFuture2.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(final FutureDone future) throws Exception { - if (future.isSuccess()) { - final Message replyMessage = future.object(); - final Thread holePunchScheduler = new Thread(new HolePScheduler(peer.peerBean().holePNumberOfPunches(), thisInstance)); - holePunchScheduler.start(); - replyMessageFuture.done(replyMessage); - } else { - replyMessageFuture2.failed("No ReplyMessage could be created!"); - } - } - }); - } else { - replyMessageFuture.failed("No ChannelFuture could be created!"); - } - } - }); - return replyMessageFuture; - } - - /** - * This methods is only called by a {@link HolePScheduler}. It simply - * creates a dummyMessage and sends it from a given localPort ( - * {@link ChannelFuture}) to a given remotePort. This procedure then punches - * the holes needed by the initiating {@link Peer}. - * - * @throws Exception - */ - public void tryConnect() throws Exception { - if (channelFutures.size() != portMappings.size()) { - throw new Exception("the number of channels does not match the number of ports!"); - } - - for (int i = 0; i < channelFutures.size(); i++) { - final Message dummyMessage = createDummyMessage(i); - final FutureResponse futureResponse = new FutureResponse(dummyMessage); - LOG.debug("FIRE! remotePort: " + dummyMessage.recipient().udpPort() + ", localPort: " + dummyMessage.sender().udpPort()); - peer.connectionBean().sender().afterConnect(futureResponse, dummyMessage, channelFutures.get(i), FIRE_AND_FORGET_VALUE); - } - } - - /** - * This method is responsible for the send mechanism of the - * holePInitMessage. - * - * @param mainFutureDone - * @param originalFutureResponse - * @param futures - * @param initMessage - */ - private void sendHolePInitMessage(final FutureDone mainFutureDone, final FutureResponse originalFutureResponse, - final List futures, final Message initMessage) { - final FutureChannelCreator fChannelCreator = peer.connectionBean().reservation().create(1, 0); - fChannelCreator.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureChannelCreator future) throws Exception { - if (future.isSuccess()) { - final FutureResponse holePFutureResponse = new FutureResponse(originalMessage); - // we need to know if the setUp failed. - holePFutureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureResponse future) throws Exception { - if (!future.isSuccess()) { - mainFutureDone.failed("No port information could be exchanged"); - } - } - }); - Utils.addReleaseListener(future, holePFutureResponse); - // send the holePInitMessage to one of the target peer - // relays - peer.connectionBean() - .sender() - .sendUDP(createHolePHandler(futures, mainFutureDone, originalFutureResponse), holePFutureResponse, initMessage, - future.channelCreator(), idleUDPSeconds, BROADCAST_VALUE); - LOG.debug("ChannelFutures successfully created. Initialization of hole punching started."); - } else { - mainFutureDone.failed("The creation of the channelCreator for to send the initMessage failed!"); - } - } - }); - } - - /** - * This method creates a {@link SimpleChannelInboundHandler} which sends the - * original{@link Message} to the nat peer that needs to be contacted. - * - * @param futures - * @param originalFutureResponse - * @param originalFutureResponse - * @return holePhandler - */ - private SimpleChannelInboundHandler createHolePHandler(final List futures, - final FutureDone futureDone, final FutureResponse originalFutureResponse) { - final SimpleChannelInboundHandler holePunchInboundHandler = new SimpleChannelInboundHandler() { - @Override - protected void channelRead0(final ChannelHandlerContext ctx, final Message msg) throws Exception { - final List portList = checkReplyValues(msg, futureDone); - if (portList != null) { - final int numberOfConnectionAttempts = portList.size() / 2; - final AtomicInteger countDown = new AtomicInteger(numberOfConnectionAttempts); - for (int i = 0; i < portList.size(); i++) { - // this ensures, that if all hole punch attemps fail, - // the system is still able to send the message via - // relaying without the user noticing it - final FutureResponse holePFutureResponse = handleFutureResponse(originalFutureResponse, portList, i, countDown, - numberOfConnectionAttempts); - - final int localport = extractLocalPort(futureDone, portList, i); - final ChannelFuture channelFuture = extractChannelFuture(futures, localport); - if (channelFuture == null) { - futureDone.failed("Something went wrong with the portmappings!"); - } - i++; - final Message sendMessage = createSendOriginalMessage(portList.get(i - 1), portList.get(i)); - peer.connectionBean().sender().afterConnect(holePFutureResponse, sendMessage, channelFuture, false); - LOG.debug("originalMessage has been sent to the other peer! {}", sendMessage); - } - } - } - - /** - * this ensures, that if all hole punch attemps fail, the system is - * still able to send the message via relaying without the user - * noticing it. In case of a succesful transmission, it also - * forwards the response message to the original FutureResponse. - * - * @param originalFutureResponse - * @param portList - * @param index - * @param countDown - * @param numberOfConnectionAttempts - * @return - */ - private FutureResponse handleFutureResponse(final FutureResponse originalFutureResponse, final List portList, - final int index, final AtomicInteger countDown, final int numberOfConnectionAttempts) { - final int listIndex = index / 2; - final FutureResponse holePFutureResponse = futureResponses.get(listIndex); - holePFutureResponse.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureResponse future) throws Exception { - if (future.isSuccess()) { - if (!originalFutureResponse.isCompleted()) { - originalFutureResponse.response(future.responseMessage()); - } - } else { - countDown.decrementAndGet(); - if (countDown.get() == 0) { - originalFutureResponse.failed("All " + numberOfConnectionAttempts + " connection attempts failed!"); - } - } - } - }); - return holePFutureResponse; - } - - /** - * ExtractLocalPort is a method which returns the portnumber of the - * previously assigned socket given a guessedPort. This method is - * needed, because the the ports on which the target peer will be - * contacted may not be the same as the ports which were assigned at - * the time of the creation of the channelFutures. - * - * @param futureDone - * @param portList - * @param index - * @return - */ - private int extractLocalPort(final FutureDone futureDone, final List portList, final int index) { - int localport = -1; - if (portMappings.isEmpty()) { - localport = portList.get(index); - } else { - for (Pair entry : portMappings) { - if ((int) entry.element0() == portList.get(index)) { - localport = (int) entry.element1(); - } - } - } - if (localport < 1) { - futureDone.failed("No mapping available for port " + portList.get(index) + "!"); - } - return localport; - } - }; - - LOG.debug("new HolePunchHandler created, waiting now for answer from rendez-vous peer."); - return holePunchInboundHandler; - } - - /** - * This method creates the inboundHandler for the replyMessage of the peer - * that we want to send a message to. - * - * @return inboundHandler - */ - private SimpleChannelInboundHandler createAfterHolePHandler(final FutureDone mainFutureDone) { - final SimpleChannelInboundHandler inboundHandler = new SimpleChannelInboundHandler() { - @Override - protected synchronized void channelRead0(final ChannelHandlerContext ctx, final Message msg) throws Exception { - if (Message.Type.OK == msg.type() && originalMessage.command() == msg.command()) { - LOG.debug("Successfully transmitted the original message to peer:[" + msg.sender().toString() - + "]. Now here's the reply:[" + msg.toString() + "]"); - mainFutureDone.done(msg); - ctx.close(); - } else if (Message.Type.REQUEST_3 == msg.type() && Commands.HOLEP.getNr() == msg.command()) { - LOG.debug("Holes successfully punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " - + msg.sender().udpPort() + "}!"); - } else { - LOG.debug("Holes punche not punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " - + msg.sender().udpPort() + "} yet!"); - } - } - }; - return inboundHandler; - } - - /** - * This method looks up a {@Link ChannelFuture} from the - * channelFutures {@link List}. If the {@Link ChannelFuture} can't be - * found it returns null instead. - * - * @param futures - * @param localPort - * @return - */ - private ChannelFuture extractChannelFuture(final List futures, final int localPort) { - for (ChannelFuture future : futures) { - if (future.channel().localAddress() != null) { - final InetSocketAddress inetSocketAddress = (InetSocketAddress) future.channel().localAddress(); - if (inetSocketAddress.getPort() == localPort) { - return future; - } - } - } - return null; - } - - /** - * this method checks if the returned values from the replying nat peer are - * valid. - * - * @param msg - * @return ok - */ - @SuppressWarnings("unchecked") - private List checkReplyValues(final Message msg, final FutureDone futureDone) { - if (msg.command() == Commands.HOLEP.getNr() && msg.type() == Type.OK) { - List portList = null; - try { - portList = (List) Utils.decodeJavaObject(msg.buffer(0).buffer()); - } catch (final Exception e) { - futureDone.failed("The decoding of the buffer threw an exception!"); - e.printStackTrace(); - return null; - } - // the list with the ports should never be Empty - if (!portList.isEmpty()) { - final int rawNumberOfHoles = portList.size(); - // the number of ports must be even! - if ((rawNumberOfHoles % 2) == 0) { - return portList; - } else { - futureDone.failed("The number of ports in the Buffer was odd! This should never happen"); - } - } else { - futureDone.failed("IntList in replyMessage was null or Empty! No ports available!!!!"); - } - } else { - futureDone.failed("Could not acquire a connection via hole punching, got: " + msg); - } - return null; - } - - /** - * This method avoids duplicate code. - * - * @param portList - * @return - * @throws IOException - */ - protected Buffer encodePortList(final List portList) throws IOException { - final byte[] bytes = Utils.encodeJavaObject(portList); - final Buffer byteBuf = new Buffer(Unpooled.wrappedBuffer(bytes)); - return byteBuf; - } - - /* - * =============================== MESSAGES =============================== - */ - - /** - * This method duplicates the original {@link Message} multiple times. This - * is needed, because the {@link Buffer} can only be read once. - * - * @param originalMessage - * @param localPort - * @param remotePort - * @return - */ - private Message createSendOriginalMessage(final int localPort, final int remotePort) { - final PeerAddress sender = originalMessage.sender().changePorts(-1, localPort).changeFirewalledTCP(false).changeFirewalledUDP(false) - .changeRelayed(false); - final PeerAddress recipient = originalMessage.recipient().changePorts(-1, remotePort).changeFirewalledTCP(false) - .changeFirewalledUDP(false).changeRelayed(false); - final Message sendMessage = createHolePMessage(recipient, sender, originalMessage.command(), originalMessage.type()); - sendMessage.version(originalMessage.version()); - sendMessage.intValue(originalMessage.messageId()); - sendMessage.udp(true); - sendMessage.expectDuplicate(true); - for (Buffer buf : originalMessage.bufferList()) { - sendMessage.buffer(new Buffer(buf.buffer().duplicate())); - } - return sendMessage; - } - - /** - * This method creates the initial {@link Message} with {@link Commands} - * .HOLEP and {@link Type}.REQUEST_1. This {@link Message} will be forwarded - * to the rendez-vous server (a relay of the remote peer) and initiate the - * hole punching procedure on the other peer. This method also calls the - * doPortGuessingInitiatingPeer(...) method of its subclass implementation - * in order to gain the correct ports. - * - * @param message - * @param channelCreator - * @return holePMessage - */ - private FutureDone createInitMessage(final List channelFutures) throws Exception { - final FutureDone initMessageFutureDone = new FutureDone(); - final PeerSocketAddress socketAddress = Utils.extractRandomRelay(originalMessage); - // we need to make a copy of the original Message - final PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) - .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); - final Message initMessage = createHolePMessage(recipient, originalMessage.sender(), RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_1); - initMessage.version(originalMessage.version()); - initMessage.udp(true); - doPortGuessingInitiatingPeer(initMessage, initMessageFutureDone, channelFutures); - LOG.debug("Hole punch initMessage created {}", initMessage.toString()); - return initMessageFutureDone; - } - - /** - * This method will create so called dummy messages without any content. - * Such methods are needed to create the port mapping entries in the peers - * NAT device. - * - * @param index - * i - * @return dummyMessage - */ - private Message createDummyMessage(final int index) { - final int remotePort = portMappings.get(index).element0(); - final int localPort = portMappings.get(index).element1(); - final PeerAddress recipient = originalSender.changeFirewalledUDP(false).changeRelayed(false).changePorts(-1, remotePort); - final PeerAddress sender = peer.peerBean().serverPeerAddress().changePorts(-1, localPort); - final Message dummyMessage = createHolePMessage(recipient, sender, RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_3); - dummyMessage.udp(true); - return dummyMessage; - } - - /** - * This method creates the reply {@link Message} with {@link Commands} - * .HOLEP and {@link Type}.REQUEST_2. This method also calls the - * doPortGuessingTargetPeer(...) method of its subclass implementation in - * order to gain the correct ports. - * - * @return - * @throws Exception - */ - private FutureDone createReplyMessage() throws Exception { - final FutureDone replyMessageFuture2 = new FutureDone(); - final Message replyMessage = createHolePMessage(originalMessage.sender(), peer.peerBean().serverPeerAddress(), Commands.HOLEP.getNr(), - Type.OK); - replyMessage.messageId(originalMessage.messageId()); - doPortGuessingTargetPeer(replyMessage, replyMessageFuture2); - return replyMessageFuture2; - } - - /** - * This is a generic method which creates a {@link Message} with the basic - * parameters. The method avoids duplicate code. - * - * @param recipient - * @param sender - * @param command - * @param type - * @return holePMessage - */ - private Message createHolePMessage(final PeerAddress recipient, final PeerAddress sender, final byte command, final Message.Type type) { - final Message message = new Message(); - message.recipient(recipient); - message.sender(sender); - message.command(command); - message.type(type); - return message; - } -} +package net.tomp2p.holep.strategy; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.util.concurrent.EventExecutorGroup; +import io.netty.util.concurrent.GenericFutureListener; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import net.tomp2p.connection.Dispatcher; +import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.FutureChannelCreator; +import net.tomp2p.futures.FutureDone; +import net.tomp2p.futures.FutureResponse; +import net.tomp2p.holep.DuplicatesHandler; +import net.tomp2p.holep.HolePInitiatorImpl; +import net.tomp2p.holep.HolePScheduler; +import net.tomp2p.holep.NATType; +import net.tomp2p.message.Buffer; +import net.tomp2p.message.Message; +import net.tomp2p.message.Message.Type; +import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.rpc.RPC; +import net.tomp2p.rpc.RPC.Commands; +import net.tomp2p.utils.Pair; +import net.tomp2p.utils.Utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DO NOT INSTANCIATE THIS CLASS!
+ *
+ * + * If you need to add a new supported nat type please extend this class and + * change also {@link NATType} and {@link NATTypeDetection}.
+ *
+ * + * This class is responsible for the whole hole punching procedure. It covers + * all aspects of the procedure on the sender and the recipient side. + * + * + * @author Jonas Wagner + * + */ +public abstract class AbstractHolePStrategy implements HolePStrategy { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractHolePStrategy.class); + private final int numberOfHoles; + private final int idleUDPSeconds; + private List futureResponses = new ArrayList(); + private PeerAddress originalSender; + protected final Peer peer; + protected final Message originalMessage; + protected volatile List channelFutures = new ArrayList(); + protected volatile List> portMappings = new ArrayList>(); + + /** + * This constructor should never be called by the user, since it should be + * called by its strategy pattern instances like + * {@link PortPreservingStrategy}. + * + * @param peer + * @param numberOfHoles + * @param idleUDPSeconds + * @param originalMessage + */ + protected AbstractHolePStrategy(final Peer peer, final int numberOfHoles, final int idleUDPSeconds, final Message originalMessage) { + this.peer = peer; + this.numberOfHoles = numberOfHoles; + this.idleUDPSeconds = idleUDPSeconds; + this.originalMessage = originalMessage; + LOG.trace("new HolePuncher created, originalMessage {}", originalMessage.toString()); + } + + /** + * This method cares about which socket contacts which socket on the NATs + * which are needed to be traversed. + * + * @param replyMessageFuture2 + * @param replyMessage + */ + protected abstract void doPortGuessingTargetPeer(final Message replyMessage, final FutureDone replyMessageFuture2) + throws Exception; + + /** + * This method needs to be overwritten by each strategy in order to let the + * other peer know which ports it need to contact. + * + * @param holePMessage + * @param initMessageFutureDone + * @param channelFutures2 + */ + protected abstract void doPortGuessingInitiatingPeer(final Message holePMessage, final FutureDone initMessageFutureDone, + final List channelFutures2) throws Exception; + + /** + * This method does two things. If the initiating peer calls it, he gets + * back a {@link List} of new {@link SimpleInboundHandler} to deal with the + * replies of the replying peer. If a replying peer is calling this method + * it will return a {@link List} of default {@link SimpleInboundHandler}s + * from the {@link Dispatcher}. + * + * @param futureResponse + * @return handlerList + */ + protected List>> prepareHandlers(final boolean initiator, + final FutureDone futureDone) { + final List>> handlerList = new ArrayList>>( + numberOfHoles); + SimpleChannelInboundHandler inboundHandler; + Map> handlers; + + if (initiator) { + for (int i = 0; i < numberOfHoles; i++) { + // we need an own futureresponse for every hole we try to punch + futureResponses.add(new FutureResponse(originalMessage)); + inboundHandler = createAfterHolePHandler(futureDone); + handlers = peer.connectionBean().sender().configureHandlers(inboundHandler, futureResponses.get(i), idleUDPSeconds, false); + handlerList.add(handlers); + } + } else { + inboundHandler = new DuplicatesHandler(peer.connectionBean().dispatcher()); + for (int i = 0; i < numberOfHoles; i++) { + // we need an own futureresponse for every hole we try to punch + futureResponses.add(new FutureResponse(originalMessage)); + handlers = peer.connectionBean().sender().configureHandlers(inboundHandler, futureResponses.get(i), idleUDPSeconds, false); + handlerList.add(handlers); + } + } + + return handlerList; + } + + /** + * This is a generic method which creates a number of {@link ChannelFuture}s + * and calls the associated {@link FutureDone} as soon as they're done. + * + * @param futureResponse + * @param handlersList + * @return fDoneChannelFutures + */ + protected FutureDone> createChannelFutures( + final List>> handlersList, final FutureDone mainFutureDone, + final int numberOfHoles) { + + final FutureDone> fDoneChannelFutures = new FutureDone>(); + final AtomicInteger countDown = new AtomicInteger(numberOfHoles); + final List channelFutures = new ArrayList(); + + for (int i = 0; i < numberOfHoles; i++) { + final FutureResponse futureResponse = futureResponses.get(i); + final Map> handlers = handlersList.get(i); + final FutureChannelCreator fcc = peer.connectionBean().reservation().create(1, 0); + Utils.addReleaseListener(fcc, futureResponse); + fcc.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureChannelCreator future) throws Exception { + if (future.isSuccess()) { + final ChannelFuture cF = future.channelCreator().createUDP(BROADCAST_VALUE, handlers, futureResponse, false); + cF.addListener(new GenericFutureListener() { + @Override + public void operationComplete(final ChannelFuture future) throws Exception { + if (future.isSuccess()) { + channelFutures.add(future); + } else { + mainFutureDone.failed("Error while creating the ChannelFutures!"); + } + countDown.decrementAndGet(); + if (countDown.get() == 0) { + fDoneChannelFutures.done(channelFutures); + } + } + }); + } else { + countDown.decrementAndGet(); + mainFutureDone.failed("Error while creating the ChannelFutures!"); + } + } + }); + } + return fDoneChannelFutures; + } + + /** + * This method initiates the hole punch procedure. + * + * @param mainFutureDone + * @param originalChannelCreator + * @param originalFutureResponse + * @param natType + * @return mainFutureDone A FutureDone which if successful contains + * the response Message from the peer we want to contact + */ + public FutureDone initiateHolePunch(final FutureDone mainFutureDone, final FutureResponse originalFutureResponse) { + //check if testCase == true + if (((HolePInitiatorImpl) peer.peerBean().holePunchInitiator()).isTestCase()) { + mainFutureDone.failed("Gandalf says: You shall not pass!!!"); + return mainFutureDone; + } + final FutureDone> fDoneChannelFutures = createChannelFutures(prepareHandlers(true, mainFutureDone), + mainFutureDone, numberOfHoles); + fDoneChannelFutures.addListener(new BaseFutureAdapter>>() { + @Override + public void operationComplete(final FutureDone> future) throws Exception { + if (future.isSuccess()) { + final List futures = future.object(); + final FutureDone initMessage = createInitMessage(futures); + initMessage.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(final FutureDone future) throws Exception { + if (future.isSuccess()) { + final Message initMessage = future.object(); + sendHolePInitMessage(mainFutureDone, originalFutureResponse, futures, initMessage); + } else { + mainFutureDone.failed("The creation of the initMessage failed!"); + } + } + }); + } else { + mainFutureDone.failed("No ChannelFuture could be created!"); + } + } + }); + return mainFutureDone; + } + + /** + * This method initiates the hole punch procedure on the target peer side. + * + * @return + */ + public FutureDone replyHolePunch() { + originalSender = (PeerAddress) originalMessage.neighborsSetList().get(0).neighbors().toArray()[0]; + final FutureDone replyMessageFuture = new FutureDone(); + final HolePStrategy thisInstance = this; + final FutureDone> rmfChannelFutures = createChannelFutures(prepareHandlers(false, replyMessageFuture), + replyMessageFuture, numberOfHoles); + rmfChannelFutures.addListener(new BaseFutureAdapter>>() { + @Override + public void operationComplete(final FutureDone> future) throws Exception { + if (future.isSuccess()) { + channelFutures = future.object(); + final FutureDone replyMessageFuture2 = createReplyMessage(); + replyMessageFuture2.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(final FutureDone future) throws Exception { + if (future.isSuccess()) { + final Message replyMessage = future.object(); + final Thread holePunchScheduler = new Thread(new HolePScheduler(peer.peerBean().holePNumberOfPunches(), thisInstance)); + holePunchScheduler.start(); + replyMessageFuture.done(replyMessage); + } else { + replyMessageFuture2.failed("No ReplyMessage could be created!"); + } + } + }); + } else { + replyMessageFuture.failed("No ChannelFuture could be created!"); + } + } + }); + return replyMessageFuture; + } + + /** + * This methods is only called by a {@link HolePScheduler}. It simply + * creates a dummyMessage and sends it from a given localPort ( + * {@link ChannelFuture}) to a given remotePort. This procedure then punches + * the holes needed by the initiating {@link Peer}. + * + * @throws Exception + */ + public void tryConnect() throws Exception { + if (channelFutures.size() != portMappings.size()) { + throw new Exception("the number of channels does not match the number of ports!"); + } + + for (int i = 0; i < channelFutures.size(); i++) { + final Message dummyMessage = createDummyMessage(i); + final FutureResponse futureResponse = new FutureResponse(dummyMessage); + LOG.debug("FIRE! remotePort: " + dummyMessage.recipient().udpPort() + ", localPort: " + dummyMessage.sender().udpPort()); + peer.connectionBean().sender().afterConnect(futureResponse, dummyMessage, channelFutures.get(i), FIRE_AND_FORGET_VALUE); + } + } + + /** + * This method is responsible for the send mechanism of the + * holePInitMessage. + * + * @param mainFutureDone + * @param originalFutureResponse + * @param futures + * @param initMessage + */ + private void sendHolePInitMessage(final FutureDone mainFutureDone, final FutureResponse originalFutureResponse, + final List futures, final Message initMessage) { + final FutureChannelCreator fChannelCreator = peer.connectionBean().reservation().create(1, 0); + fChannelCreator.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureChannelCreator future) throws Exception { + if (future.isSuccess()) { + final FutureResponse holePFutureResponse = new FutureResponse(originalMessage); + // we need to know if the setUp failed. + holePFutureResponse.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureResponse future) throws Exception { + if (!future.isSuccess()) { + mainFutureDone.failed("No port information could be exchanged"); + } + } + }); + Utils.addReleaseListener(future, holePFutureResponse); + // send the holePInitMessage to one of the target peer + // relays + peer.connectionBean() + .sender() + .sendUDP(createHolePHandler(futures, mainFutureDone, originalFutureResponse), holePFutureResponse, initMessage, + future.channelCreator(), idleUDPSeconds, BROADCAST_VALUE); + LOG.debug("ChannelFutures successfully created. Initialization of hole punching started."); + } else { + mainFutureDone.failed("The creation of the channelCreator for to send the initMessage failed!"); + } + } + }); + } + + /** + * This method creates a {@link SimpleChannelInboundHandler} which sends the + * original{@link Message} to the nat peer that needs to be contacted. + * + * @param futures + * @param originalFutureResponse + * @param originalFutureResponse + * @return holePhandler + */ + private SimpleChannelInboundHandler createHolePHandler(final List futures, + final FutureDone futureDone, final FutureResponse originalFutureResponse) { + final SimpleChannelInboundHandler holePunchInboundHandler = new SimpleChannelInboundHandler() { + @Override + protected void channelRead0(final ChannelHandlerContext ctx, final Message msg) throws Exception { + final List portList = checkReplyValues(msg, futureDone); + if (portList != null) { + final int numberOfConnectionAttempts = portList.size() / 2; + final AtomicInteger countDown = new AtomicInteger(numberOfConnectionAttempts); + for (int i = 0; i < portList.size(); i++) { + // this ensures, that if all hole punch attemps fail, + // the system is still able to send the message via + // relaying without the user noticing it + final FutureResponse holePFutureResponse = handleFutureResponse(originalFutureResponse, portList, i, countDown, + numberOfConnectionAttempts); + + final int localport = extractLocalPort(futureDone, portList, i); + final ChannelFuture channelFuture = extractChannelFuture(futures, localport); + if (channelFuture == null) { + futureDone.failed("Something went wrong with the portmappings!"); + } + i++; + final Message sendMessage = createSendOriginalMessage(portList.get(i - 1), portList.get(i)); + peer.connectionBean().sender().afterConnect(holePFutureResponse, sendMessage, channelFuture, false); + LOG.debug("originalMessage has been sent to the other peer! {}", sendMessage); + } + } + } + + /** + * this ensures, that if all hole punch attemps fail, the system is + * still able to send the message via relaying without the user + * noticing it. In case of a succesful transmission, it also + * forwards the response message to the original FutureResponse. + * + * @param originalFutureResponse + * @param portList + * @param index + * @param countDown + * @param numberOfConnectionAttempts + * @return + */ + private FutureResponse handleFutureResponse(final FutureResponse originalFutureResponse, final List portList, + final int index, final AtomicInteger countDown, final int numberOfConnectionAttempts) { + final int listIndex = index / 2; + final FutureResponse holePFutureResponse = futureResponses.get(listIndex); + holePFutureResponse.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureResponse future) throws Exception { + if (future.isSuccess()) { + if (!originalFutureResponse.isCompleted()) { + originalFutureResponse.response(future.responseMessage()); + } + } else { + countDown.decrementAndGet(); + if (countDown.get() == 0) { + originalFutureResponse.failed("All " + numberOfConnectionAttempts + " connection attempts failed!"); + } + } + } + }); + return holePFutureResponse; + } + + /** + * ExtractLocalPort is a method which returns the portnumber of the + * previously assigned socket given a guessedPort. This method is + * needed, because the the ports on which the target peer will be + * contacted may not be the same as the ports which were assigned at + * the time of the creation of the channelFutures. + * + * @param futureDone + * @param portList + * @param index + * @return + */ + private int extractLocalPort(final FutureDone futureDone, final List portList, final int index) { + int localport = -1; + if (portMappings.isEmpty()) { + localport = portList.get(index); + } else { + for (Pair entry : portMappings) { + if ((int) entry.element0() == portList.get(index)) { + localport = (int) entry.element1(); + } + } + } + if (localport < 1) { + futureDone.failed("No mapping available for port " + portList.get(index) + "!"); + } + return localport; + } + }; + + LOG.debug("new HolePunchHandler created, waiting now for answer from rendez-vous peer."); + return holePunchInboundHandler; + } + + /** + * This method creates the inboundHandler for the replyMessage of the peer + * that we want to send a message to. + * + * @return inboundHandler + */ + private SimpleChannelInboundHandler createAfterHolePHandler(final FutureDone mainFutureDone) { + final SimpleChannelInboundHandler inboundHandler = new SimpleChannelInboundHandler() { + @Override + protected synchronized void channelRead0(final ChannelHandlerContext ctx, final Message msg) throws Exception { + if (Message.Type.OK == msg.type() && originalMessage.command() == msg.command()) { + LOG.debug("Successfully transmitted the original message to peer:[" + msg.sender().toString() + + "]. Now here's the reply:[" + msg.toString() + "]"); + mainFutureDone.done(msg); + ctx.close(); + } else if (Message.Type.REQUEST_3 == msg.type() && Commands.HOLEP.getNr() == msg.command()) { + LOG.debug("Holes successfully punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " + + msg.sender().udpPort() + "}!"); + } else { + LOG.debug("Holes punche not punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " + + msg.sender().udpPort() + "} yet!"); + } + } + }; + return inboundHandler; + } + + /** + * This method looks up a {@Link ChannelFuture} from the + * channelFutures {@link List}. If the {@Link ChannelFuture} can't be + * found it returns null instead. + * + * @param futures + * @param localPort + * @return + */ + private ChannelFuture extractChannelFuture(final List futures, final int localPort) { + for (ChannelFuture future : futures) { + if (future.channel().localAddress() != null) { + final InetSocketAddress inetSocketAddress = (InetSocketAddress) future.channel().localAddress(); + if (inetSocketAddress.getPort() == localPort) { + return future; + } + } + } + return null; + } + + /** + * this method checks if the returned values from the replying nat peer are + * valid. + * + * @param msg + * @return ok + */ + @SuppressWarnings("unchecked") + private List checkReplyValues(final Message msg, final FutureDone futureDone) { + if (msg.command() == Commands.HOLEP.getNr() && msg.type() == Type.OK) { + List portList = null; + try { + portList = (List) Utils.decodeJavaObject(msg.buffer(0).buffer()); + } catch (final Exception e) { + futureDone.failed("The decoding of the buffer threw an exception!"); + e.printStackTrace(); + return null; + } + // the list with the ports should never be Empty + if (!portList.isEmpty()) { + final int rawNumberOfHoles = portList.size(); + // the number of ports must be even! + if ((rawNumberOfHoles % 2) == 0) { + return portList; + } else { + futureDone.failed("The number of ports in the Buffer was odd! This should never happen"); + } + } else { + futureDone.failed("IntList in replyMessage was null or Empty! No ports available!!!!"); + } + } else { + futureDone.failed("Could not acquire a connection via hole punching, got: " + msg); + } + return null; + } + + /** + * This method avoids duplicate code. + * + * @param portList + * @return + * @throws IOException + */ + protected Buffer encodePortList(final List portList) throws IOException { + final byte[] bytes = Utils.encodeJavaObject(portList); + final Buffer byteBuf = new Buffer(Unpooled.wrappedBuffer(bytes)); + return byteBuf; + } + + /* + * =============================== MESSAGES =============================== + */ + + /** + * This method duplicates the original {@link Message} multiple times. This + * is needed, because the {@link Buffer} can only be read once. + * + * @param originalMessage + * @param localPort + * @param remotePort + * @return + */ + private Message createSendOriginalMessage(final int localPort, final int remotePort) { + final PeerAddress sender = originalMessage.sender().changePorts(-1, localPort).changeFirewalledTCP(false).changeFirewalledUDP(false) + .changeRelayed(false); + final PeerAddress recipient = originalMessage.recipient().changePorts(-1, remotePort).changeFirewalledTCP(false) + .changeFirewalledUDP(false).changeRelayed(false); + final Message sendMessage = createHolePMessage(recipient, sender, originalMessage.command(), originalMessage.type()); + sendMessage.version(originalMessage.version()); + sendMessage.intValue(originalMessage.messageId()); + sendMessage.udp(true); + sendMessage.expectDuplicate(true); + for (Buffer buf : originalMessage.bufferList()) { + sendMessage.buffer(new Buffer(buf.buffer().duplicate())); + } + return sendMessage; + } + + /** + * This method creates the initial {@link Message} with {@link Commands} + * .HOLEP and {@link Type}.REQUEST_1. This {@link Message} will be forwarded + * to the rendez-vous server (a relay of the remote peer) and initiate the + * hole punching procedure on the other peer. This method also calls the + * doPortGuessingInitiatingPeer(...) method of its subclass implementation + * in order to gain the correct ports. + * + * @param message + * @param channelCreator + * @return holePMessage + */ + private FutureDone createInitMessage(final List channelFutures) throws Exception { + final FutureDone initMessageFutureDone = new FutureDone(); + final PeerSocketAddress socketAddress = Utils.extractRandomRelay(originalMessage); + // we need to make a copy of the original Message + final PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) + .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); + final Message initMessage = createHolePMessage(recipient, originalMessage.sender(), RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_1); + initMessage.version(originalMessage.version()); + initMessage.udp(true); + doPortGuessingInitiatingPeer(initMessage, initMessageFutureDone, channelFutures); + LOG.debug("Hole punch initMessage created {}", initMessage.toString()); + return initMessageFutureDone; + } + + /** + * This method will create so called dummy messages without any content. + * Such methods are needed to create the port mapping entries in the peers + * NAT device. + * + * @param index + * i + * @return dummyMessage + */ + private Message createDummyMessage(final int index) { + final int remotePort = portMappings.get(index).element0(); + final int localPort = portMappings.get(index).element1(); + final PeerAddress recipient = originalSender.changeFirewalledUDP(false).changeRelayed(false).changePorts(-1, remotePort); + final PeerAddress sender = peer.peerBean().serverPeerAddress().changePorts(-1, localPort); + final Message dummyMessage = createHolePMessage(recipient, sender, RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_3); + dummyMessage.udp(true); + return dummyMessage; + } + + /** + * This method creates the reply {@link Message} with {@link Commands} + * .HOLEP and {@link Type}.REQUEST_2. This method also calls the + * doPortGuessingTargetPeer(...) method of its subclass implementation in + * order to gain the correct ports. + * + * @return + * @throws Exception + */ + private FutureDone createReplyMessage() throws Exception { + final FutureDone replyMessageFuture2 = new FutureDone(); + final Message replyMessage = createHolePMessage(originalMessage.sender(), peer.peerBean().serverPeerAddress(), Commands.HOLEP.getNr(), + Type.OK); + replyMessage.messageId(originalMessage.messageId()); + doPortGuessingTargetPeer(replyMessage, replyMessageFuture2); + return replyMessageFuture2; + } + + /** + * This is a generic method which creates a {@link Message} with the basic + * parameters. The method avoids duplicate code. + * + * @param recipient + * @param sender + * @param command + * @param type + * @return holePMessage + */ + private Message createHolePMessage(final PeerAddress recipient, final PeerAddress sender, final byte command, final Message.Type type) { + final Message message = new Message(); + message.recipient(recipient); + message.sender(sender); + message.command(command); + message.type(type); + return message; + } +} diff --git a/pom.xml b/pom.xml index 01d7e78c8..4df52f82a 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ - 4.0.28.Final + 4.0.32.Final From 5e0a71e1db1d01b976557f91830caddcd9c8b8ef Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Sun, 4 Oct 2015 20:03:52 +0200 Subject: [PATCH 081/135] added send self when a peer is responsible for an ID --- .../connection/DefaultSendBehavior.java | 14 +++++++++++-- .../net/tomp2p/connection/Dispatcher.java | 9 ++++++++ .../net/tomp2p/connection/SendBehavior.java | 5 +++-- .../java/net/tomp2p/connection/Sender.java | 21 ++----------------- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java index 10d45f958..1fd1713a3 100644 --- a/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java +++ b/core/src/main/java/net/tomp2p/connection/DefaultSendBehavior.java @@ -15,11 +15,16 @@ public class DefaultSendBehavior implements SendBehavior { private static final int MTU = 1000; @Override - public SendMethod tcpSendBehavior(Message message) { + public SendMethod tcpSendBehavior(Dispatcher dispatcher, Message message) { if(message.recipient().peerId().equals(message.sender().peerId())) { // shortcut, just send to yourself return SendMethod.SELF; } + //also check if we have multiple peers + if(dispatcher.responsibleFor(message.recipient().peerId())) { + // shortcut, just send to yourself + return SendMethod.SELF; + } if(message.recipientReflected() != null) { return SendMethod.DIRECT; @@ -45,11 +50,16 @@ public SendMethod tcpSendBehavior(Message message) { } @Override - public SendMethod udpSendBehavior(Message message) throws UnsupportedOperationException { + public SendMethod udpSendBehavior(Dispatcher dispatcher, Message message) throws UnsupportedOperationException { if(message.recipient().peerId().equals(message.sender().peerId())) { // shortcut, just send to yourself return SendMethod.SELF; } + //also check if we have multiple peers + if(dispatcher.responsibleFor(message.recipient().peerId())) { + // shortcut, just send to yourself + return SendMethod.SELF; + } if(message.recipientReflected() != null) { return SendMethod.DIRECT; diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 372d83519..b237ff8ab 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -473,4 +473,13 @@ public void run() { public Map getPendingRequests() { return pendingRequests; } + + public boolean responsibleFor(Number160 peerId) { + readLock.lock(); + try { + return ioHandlers.containsKey(new Number320(peerId, peerId)); + } finally { + readLock.unlock(); + } + } } diff --git a/core/src/main/java/net/tomp2p/connection/SendBehavior.java b/core/src/main/java/net/tomp2p/connection/SendBehavior.java index 803c11fc0..24d46f95b 100644 --- a/core/src/main/java/net/tomp2p/connection/SendBehavior.java +++ b/core/src/main/java/net/tomp2p/connection/SendBehavior.java @@ -6,6 +6,7 @@ * Decice how a direct message is sent. * * @author Nico Rutishauser + * @author Thomas Bocek * */ public interface SendBehavior { @@ -47,7 +48,7 @@ public enum SendMethod { * the message to be sent * @return the sending behavior which should be used */ - SendMethod tcpSendBehavior(Message message); + SendMethod tcpSendBehavior(Dispatcher dispatcher, Message message); /** * Returns the send behavior depending on the message to be sent over UDP. @@ -58,5 +59,5 @@ public enum SendMethod { * @throws UnsupportedOperationException * sending over UDP is not allowed for this message. */ - SendMethod udpSendBehavior(Message message) throws UnsupportedOperationException; + SendMethod udpSendBehavior(Dispatcher dispatcher, Message message) throws UnsupportedOperationException; } diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index f8b53feaf..66e2f1460 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -158,7 +158,7 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu } else if (channelCreator != null) { final TimeoutFactory timeoutHandler = createTimeoutHandler(futureResponse, idleTCPMillis, handler == null); - switch (sendBehavior.tcpSendBehavior(message)) { + switch (sendBehavior.tcpSendBehavior(dispatcher, message)) { case DIRECT: connectAndSend(handler, futureResponse, channelCreator, connectTimeoutMillis, peerConnection, timeoutHandler, message); break; @@ -530,7 +530,7 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu try { ChannelFuture channelFuture = null; - switch (sendBehavior.udpSendBehavior(message)) { + switch (sendBehavior.udpSendBehavior(dispatcher, message)) { case DIRECT: channelFuture = channelCreator.createUDP(broadcast, handlers, futureResponse, isFireAndForget); break; @@ -814,23 +814,6 @@ public void operationComplete(final ChannelFuture arg0) throws Exception { }); } - /** - * Report a successful response after the channel was closed. - * - * @param futureResponse - * The future to set the response - * @param close - * The close future - */ - private void reportMessage(final FutureResponse futureResponse, final ChannelFuture close) { - close.addListener(new GenericFutureListener() { - @Override - public void operationComplete(final ChannelFuture arg0) throws Exception { - futureResponse.responseNow(); - } - }); - } - /** * @param channelFuture * The channel future that can be canceled From a37cf370c79cf2e6bc85f357f5d7cba614087d77 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 6 Oct 2015 13:20:56 +0200 Subject: [PATCH 082/135] avoid memory copy --- core/src/main/java/net/tomp2p/utils/Utils.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index 631dbf7b9..e78487f20 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -266,13 +266,26 @@ public static byte[] uncompress(byte[] compressedData, int offset, int length) { public static byte[] uncompress(byte[] compressedData) { return uncompress(compressedData, 0, compressedData.length); } + + //save memory: http://stackoverflow.com/a/26850863 + /** Subclasses ByteArrayOutputStream to give access to the internal raw buffer. */ + private static class ByteArrayOutputStream2 extends ByteArrayOutputStream { + public ByteArrayOutputStream2() { super(); } + + /** Returns the internal buffer of this ByteArrayOutputStream, without copying. */ + public synchronized byte[] buf() { + return this.buf; + } + } public static byte[] encodeJavaObject(Object attachement) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ByteArrayOutputStream2 bos = new ByteArrayOutputStream2(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(attachement); // no need to call close or flush since we use ByteArrayOutputStream - byte[] data = bos.toByteArray(); + byte[] data = bos.buf(); + //no need to call this, but it gives a warning if not called + oos.close(); return data; } From 90f4fb434311edb3cc14cd5ad4a08a4cbcd6138a Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 11:10:13 +0200 Subject: [PATCH 083/135] fixed ConcurrentModificationException --- dht/src/main/java/net/tomp2p/dht/StorageMemory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java index b6a583204..44f263865 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java @@ -20,7 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; +//import java.util.HashSet; import java.util.Map; import java.util.NavigableMap; import java.util.Set; @@ -212,7 +212,7 @@ public boolean updateResponsibilities(Number160 locationKey, Number160 peerId) { } Set contentIDs = responsibilityMapRev.get(peerId); if(contentIDs == null) { - contentIDs = new HashSet(); + contentIDs = Collections.newSetFromMap(new ConcurrentHashMap()); responsibilityMapRev.put(peerId, contentIDs); } contentIDs.add(locationKey); From bf2b0e973687cb693da30b1b69026ec1a6ccf549 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 14:10:52 +0200 Subject: [PATCH 084/135] when sendtoself, always add to map, as we have full trust --- .../java/net/tomp2p/connection/Sender.java | 5 ++++ .../main/java/net/tomp2p/message/Message.java | 26 +++++++++++-------- .../java/net/tomp2p/rpc/DispatchHandler.java | 4 ++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 66e2f1460..07869a86a 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -370,6 +370,11 @@ public Data filter(Data data, boolean isConvertMeta, boolean isReply) { }); final DispatchHandler handler = dispatcher.associatedHandler(copy); + if(handler == null) { + LOG.error("No handler found for self message {}", message); + return; + } + handler.forwardMessage(copy, null, new Responder() { @Override diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index ac5fda1fc..300a8b1e9 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -1156,17 +1156,21 @@ public Message duplicate(DataFilter dataFilter) { message.peerSocketAddressList = this.peerSocketAddressList; message.signatureEncode = this.signatureEncode; - // these are transient - //presetContentTypes - //privateKey; - //senderSocket; - //recipientSocket; - //udp; - //done; - //sign; - //content; - //verified; - //sendSelf; + // these are transient, copy anyway + + message.presetContentTypes = presetContentTypes; + + message.privateKey = this.privateKey; + message.senderSocket = this.senderSocket; + message.recipientSocket = this.recipientSocket; + message.udp = this.udp; + message.done = this.done; + message.sign = this.sign; + message.content = this.content; + message.verified = this.verified; + message.sendSelf = this.sendSelf; + message.recipientRelay = this.recipientRelay; + message.recipientReflected = this.recipientReflected; return message; } diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index d4e6cee0c..f6c1251b2 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -161,7 +161,9 @@ public void forwardMessage(final Message requestMessage, PeerConnection peerConn //request 2/ping is a ping discover, where we don't know our external address and port. Don't add this! LOG.debug("don't add the sender to the map (yet) {}", requestMessage); } else { - peerBean.notifyPeerFound(requestMessage.sender(), requestMessage.sender(), peerConnection, null); + //if its send to self, then we have full trust, don't set reporter + final PeerAddress reporter = requestMessage.isSendSelf() ? null : requestMessage.sender(); + peerBean.notifyPeerFound(requestMessage.sender(), reporter, null, null); } try { From 931b607eb54f3e6e9626d3746e09a31e95d065b3 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 14:23:27 +0200 Subject: [PATCH 085/135] test fixed --- .../test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java index 47c57ed51..8115a55ed 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java @@ -169,8 +169,8 @@ public void testRouting() throws IOException, InterruptedException { Assert.assertEquals(peer2.peerAddress(), fr.potentialHits().pollFirst() ); // The startPeer should only have contacted peer2 and not peer1 (because of maxSuccess=1, parallel=1) - Assert.assertTrue(peer2.peerBean().peerMap().containsOverflow(startPeer.peerAddress())); - Assert.assertFalse(peer1.peerBean().peerMap().containsOverflow(startPeer.peerAddress())); + Assert.assertTrue(peer2.peerBean().peerMap().contains(startPeer.peerAddress())); + Assert.assertFalse(peer1.peerBean().peerMap().contains(startPeer.peerAddress())); } finally { From 8a94d4e7f1df4a98014d68d4938fc3bc8c4cd18b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 16:51:03 +0200 Subject: [PATCH 086/135] fixing discover issues with releasing the channels too early --- .../net/tomp2p/connection/ChannelCreator.java | 6 ++- .../net/tomp2p/connection/ChannelServer.java | 5 +- .../java/net/tomp2p/connection/Sender.java | 7 +-- .../tomp2p/p2p/builder/DiscoverBuilder.java | 47 ++++++++++------ dht/src/test/java/net/tomp2p/dht/TestDHT.java | 53 +++++++++++++++++++ 5 files changed, 96 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java index df7679bdc..92f8db86f 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java @@ -150,8 +150,8 @@ public ChannelFuture createUDP(final boolean broadcast, final Map> channelHandlers2 = channelClientConfiguration.pipelineFilter().filter( channelHandlers, true, true); addHandlers(b, channelHandlers2); diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServer.java b/core/src/main/java/net/tomp2p/connection/ChannelServer.java index 73f4882f3..c05153c80 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServer.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServer.java @@ -267,6 +267,7 @@ boolean startupUDP(final InetSocketAddress listenAddresses, final ChannelServerC b.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(ConnectionBean.UDP_LIMIT)); //default is on my machine 200K, testBroadcastUDP fails with this value, as UDP packets are dropped. Increase to 2MB b.option(ChannelOption.SO_RCVBUF, 2 * 1024 * 1024); + //b.option(ChannelOption.SO_SNDBUF, 2 * 1024 * 1024); b.handler(new ChannelInitializer() { @Override @@ -300,11 +301,13 @@ boolean startupTCP(final InetSocketAddress listenAddresses, final ChannelServerC ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup); b.channel(NioServerSocketChannel.class); + //b.option(ChannelOption.SO_RCVBUF, 2 * 1024 * 1024); + //b.option(ChannelOption.SO_SNDBUF, 2 * 1024 * 1024); b.childHandler(new ChannelInitializer() { @Override protected void initChannel(final Channel ch) throws Exception { ch.config().setAllocator(channelServerConfiguration.byteBufAllocator()); - // b.option(ChannelOption.SO_BACKLOG, BACKLOG); + //bestEffortOptions(ch, ChannelOption.SO_BACKLOG, BACKLOG); bestEffortOptions(ch, ChannelOption.SO_LINGER, 0); bestEffortOptions(ch, ChannelOption.TCP_NODELAY, true); for (Map.Entry> entry : handlers(true).entrySet()) { diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 07869a86a..27691542e 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -154,6 +154,7 @@ public void sendTCP(final SimpleChannelInboundHandler handler, final Fu final ChannelFuture channelFuture; if (peerConnection != null && peerConnection.channelFuture() != null && peerConnection.channelFuture().channel().isActive()) { channelFuture = sendTCPPeerConnection(peerConnection, handler, channelCreator, futureResponse); + LOG.debug("go for peer connection / TCP"); afterConnect(futureResponse, message, channelFuture, handler == null); } else if (channelCreator != null) { final TimeoutFactory timeoutHandler = createTimeoutHandler(futureResponse, idleTCPMillis, handler == null); @@ -756,7 +757,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { final ChannelFuture writeFuture = future.channel().writeAndFlush(message); afterSend(writeFuture, futureResponse, fireAndForget); } else { - LOG.debug("Channel creation failed", future.cause()); + LOG.warn("Channel creation failed", future.cause()); futureResponse.failed("Channel creation failed " + future.channel() + "/" + future.cause()); // may have been closed by the other side, // or it may have been canceled from this side @@ -790,7 +791,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { if (!future.isSuccess()) { futureResponse.failedLater(future.cause()); reportFailed(futureResponse, future.channel().close()); - LOG.warn("Failed to write channel the request {} {}.", futureResponse.request(), future.cause()); + LOG.warn("Failed to write to channel - request {} {}.", futureResponse.request(), future.cause()); } if (fireAndForget) { futureResponse.responseLater(null); @@ -844,7 +845,7 @@ public void operationComplete(FutureResponse future) throws Exception { //do nothing, because such a (dummy) message will never reach its target the first time } if(!future.isCanceled()) { - LOG.debug("peer failed: {}", message); + LOG.debug("peer failed: {}, {}", message, future); synchronized (peerStatusListeners) { for (PeerStatusListener peerStatusListener : peerStatusListeners) { peerStatusListener.peerFailed(message.recipient(), new PeerException(future)); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 85fd7e31d..66274d1ac 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -29,7 +29,9 @@ import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; import net.tomp2p.futures.FutureDiscover; +import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FutureResponse; +import net.tomp2p.futures.Futures; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerReachable; import net.tomp2p.peers.Number160; @@ -216,26 +218,33 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio */ private void discover(final FutureDiscover futureDiscover, final PeerAddress peerAddress, final ChannelCreator cc, final ConnectionConfiguration configuration) { + + final FutureDone pingDone = new FutureDone(); peer.pingRPC().addPeerReachableListener(new PeerReachable() { private volatile boolean changedUDP = false; - private volatile boolean changedTCP = false; @Override - public void peerWellConnected(PeerAddress peerAddress, PeerAddress reporter, boolean tcp) { - if (tcp) { - changedTCP = true; - futureDiscover.discoveredTCP(); - LOG.debug("TCP discovered"); - } else { - changedUDP = true; - futureDiscover.discoveredUDP(); - LOG.debug("UDP discovered"); - } - if (changedTCP && changedUDP) { - futureDiscover.done(peerAddress, reporter); - } + public void peerWellConnected(final PeerAddress peerAddress, final PeerAddress reporter, final boolean tcp) { + pingDone.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(FutureDone future) throws Exception { + if (tcp) { + futureDiscover.discoveredTCP(); + changedTCP = true; + LOG.debug("TCP discovered"); + } else { + futureDiscover.discoveredUDP(); + changedUDP = true; + LOG.debug("UDP discovered"); + } + if (changedTCP && changedUDP) { + futureDiscover.done(peerAddress, reporter); + } + } + }); + } }); @@ -307,7 +316,7 @@ public void operationComplete(FutureResponse future) throws Exception { fr1.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureResponse future) throws Exception { - if(future.isFailed() && !futureDiscover.isCompleted()) { + if(future.isFailed() ) { LOG.warn("FutureDiscover (2): We need at least the TCP connection {} - {}", future, futureDiscover.failedReason()); futureDiscover.failed("FutureDiscover (2): We need at least the TCP connection", future); } @@ -318,11 +327,17 @@ public void operationComplete(FutureResponse future) throws Exception { fr2.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureResponse future) throws Exception { - if(future.isFailed() && !futureDiscover.isCompleted()) { + if(future.isFailed() ) { LOG.warn("FutureDiscover (2): UDP failed connection {} - {}", future, futureDiscover.failedReason()); } } }); + Futures.whenAll(fr1, fr2).addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(FutureDone future) throws Exception { + pingDone.done(); + } + }); // from here we probe, set the timeout here futureDiscover.timeout(serverAddress, peer.connectionBean().timer(), discoverTimeoutSec); return; diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index 28c9bdcab..b72098d51 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -1534,6 +1534,59 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro } } } + + @Test + public void testTooManyDiscover() throws Exception { + Peer master = null; + Peer slave = null; + try { + // since we have two peers, we need to reduce the connections -> we + // will have 300 * 2 (peer connection) + // plus 100 * 2 * 2. The last multiplication is due to discover, + // where the recipient creates a connection + // with its own limit. Since the limit is 1024 and we stop at 1000 + // only for the connection, we may run into + // too many open files + PeerBuilder masterMaker = new PeerBuilder(new Number160(rnd)).ports(4001); + master = masterMaker.enableMaintenance(false).start(); + PeerBuilder slaveMaker = new PeerBuilder(new Number160(rnd)).ports(4002); + slave = slaveMaker.enableMaintenance(false).start(); + + System.out.println("peers up and running"); + + + + List list2 = new ArrayList(); + + for (int i = 0; i < 20000; i++) { + list2.add(master.discover().peerAddress(slave.peerAddress()).start()); + + } + + for (BaseFuture bf : list2) { + bf.awaitUninterruptibly(); + bf.awaitListenersUninterruptibly(); + if (bf.isFailed()) { + System.out.println("WTF " + bf.failedReason()); + } else { + System.out.print("."); + } + Assert.assertEquals(true, bf.isSuccess()); + } + + System.out.println("done!!"); + } catch (Exception e) { + e.printStackTrace(); + } finally { + System.out.println("done!1!"); + if (master != null) { + master.shutdown().await(); + } + if (slave != null) { + slave.shutdown().await(); + } + } + } From 85a2f1ec51adf3b6e403afcc7978b79cf9887dd8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 17:37:50 +0200 Subject: [PATCH 087/135] fixing testcase --- .../net/tomp2p/replication/SynchronizationTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java b/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java index 269fddcc4..4442a8666 100644 --- a/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java +++ b/replication/src/test/java/net/tomp2p/replication/SynchronizationTest.java @@ -323,14 +323,14 @@ public void operationComplete(FutureResponse future) throws Exception { } @Test - public void testInfoMessageNOTSAMELoop() throws IOException, InterruptedException { + public void testInfoMessageNOTSAMELoop() throws IOException, InterruptedException, ClassNotFoundException { for (int i=0;i<100;i++) { testInfoMessageNOTSAME(); } } @Test - public void testInfoMessageNOTSAME() throws IOException, InterruptedException { + public void testInfoMessageNOTSAME() throws IOException, InterruptedException, ClassNotFoundException { PeerDHT sender = null; PeerDHT receiver = null; @@ -351,12 +351,12 @@ public void testInfoMessageNOTSAME() throws IOException, InterruptedException { final String value = "Test"; final String value1 = "Test1"; - sender.put(locationKey).data(new Data(value)).start().awaitUninterruptibly(); - receiver.put(locationKey).data(new Data(value1)).start().awaitUninterruptibly(); + sender.put(locationKey).data(new Data(value.getBytes())).start().awaitUninterruptibly(); + receiver.put(locationKey).data(new Data(value1.getBytes())).start().awaitUninterruptibly(); NavigableMap map = new TreeMap(); final DataMap dataMap = new DataMap(map); - map.put(new Number640(locationKey, domainKey, contentKey, Number160.ZERO), new Data("Test")); + map.put(new Number640(locationKey, domainKey, contentKey, Number160.ZERO), new Data("Test".getBytes())); sender.peer().bootstrap().peerAddress(receiver.peerAddress()).start().awaitUninterruptibly(); @@ -386,7 +386,7 @@ public void operationComplete(FutureResponse future) throws Exception { latch.await(); assertEquals(1, ref.get().size()); - assertEquals(100, ref.get().dataMap().values().iterator().next().toBytes().length); + assertEquals(60, ref.get().dataMap().values().iterator().next().toBytes().length); assertEquals(false, ref.get().dataMap().values().iterator().next().isFlag1()); assertEquals(false, ref.get().dataMap().values().iterator().next().isFlag2()); From 152f204e07c6ada9593e31631bcfd17185acfba0 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 7 Oct 2015 18:08:06 +0200 Subject: [PATCH 088/135] don't put too much pressure on the GC, reduce object size --- dht/src/test/java/net/tomp2p/dht/TestDHT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dht/src/test/java/net/tomp2p/dht/TestDHT.java b/dht/src/test/java/net/tomp2p/dht/TestDHT.java index b72098d51..6b1dfb7dc 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestDHT.java @@ -1491,7 +1491,7 @@ public Buffer reply(PeerAddress sender, Buffer requestBuffer, boolean last) thro } for (int i = 0; i < 20000; i++) { list2.add(master.discover().peerAddress(slave.peerAddress()).start()); - final byte[] b = new byte[10000]; + final byte[] b = new byte[1000]; byte[] me = Utils.intToByteArray(i); System.arraycopy(me, 0, b, 0, 4); list2.add(master.sendDirect(slave.peerAddress()).dataBuffer(new DataBuffer(Unpooled.wrappedBuffer(b))) From 3f6065de3c57c931b562660fc8200401bc850c36 Mon Sep 17 00:00:00 2001 From: Esfomeado Date: Thu, 8 Oct 2015 12:54:52 +0100 Subject: [PATCH 089/135] Minor Cleanup --- all/assembly.xml | 2 +- core/src/main/java/net/tomp2p/p2p/JobScheduler.java | 2 +- core/src/main/java/net/tomp2p/peers/IP.java | 6 +++--- core/src/main/java/net/tomp2p/peers/Number160.java | 2 +- core/src/main/java/net/tomp2p/peers/Number640.java | 2 +- core/src/main/java/net/tomp2p/utils/CacheMap.java | 2 +- nat/pom.xml | 8 +------- 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/all/assembly.xml b/all/assembly.xml index b4f94de40..193b2ee9c 100644 --- a/all/assembly.xml +++ b/all/assembly.xml @@ -46,7 +46,7 @@ ${project.build.directory} - + *.jar diff --git a/core/src/main/java/net/tomp2p/p2p/JobScheduler.java b/core/src/main/java/net/tomp2p/p2p/JobScheduler.java index aa1adcdec..221db55bd 100644 --- a/core/src/main/java/net/tomp2p/p2p/JobScheduler.java +++ b/core/src/main/java/net/tomp2p/p2p/JobScheduler.java @@ -74,7 +74,7 @@ private void shutdown() { shutdownFuture.done(); } } - }; + } public JobScheduler(Peer peer) { this(peer, 1, Executors.defaultThreadFactory()); diff --git a/core/src/main/java/net/tomp2p/peers/IP.java b/core/src/main/java/net/tomp2p/peers/IP.java index 34607dac6..de9e4854c 100644 --- a/core/src/main/java/net/tomp2p/peers/IP.java +++ b/core/src/main/java/net/tomp2p/peers/IP.java @@ -183,7 +183,7 @@ public static IPv4 fromInet4Address(final InetAddress inetAddress) { byte[] buf = ((Inet4Address) inetAddress).getAddress(); int ip = ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) - | ((buf[3] & 0xFF) << 0); + | ((buf[3] & 0xFF)); return new IPv4(ip); } @@ -197,11 +197,11 @@ public static IPv6 fromInet6Address(final InetAddress inetAddress) { long highBits = ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) | ((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) | ((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) - | ((buf[6] & 0xFFL) << 8) | ((buf[7] & 0xFFL) << 0); + | ((buf[6] & 0xFFL) << 8) | ((buf[7] & 0xFFL)); long lowBits = ((buf[8] & 0xFFL) << 56) | ((buf[9] & 0xFFL) << 48) | ((buf[10] & 0xFFL) << 40) | ((buf[11] & 0xFFL) << 32) | ((buf[12] & 0xFFL) << 24) | ((buf[13] & 0xFFL) << 16) - | ((buf[14] & 0xFFL) << 8) | ((buf[15] & 0xFFL) << 0); + | ((buf[14] & 0xFFL) << 8) | ((buf[15] & 0xFFL)); return new IPv6(highBits, lowBits); } diff --git a/core/src/main/java/net/tomp2p/peers/Number160.java b/core/src/main/java/net/tomp2p/peers/Number160.java index 17344acb0..1afd38bdd 100644 --- a/core/src/main/java/net/tomp2p/peers/Number160.java +++ b/core/src/main/java/net/tomp2p/peers/Number160.java @@ -260,7 +260,7 @@ public int toByteArray(final byte[] me, final int offset) { for (int i = 0; i < INT_ARRAY_SIZE; i++) { // multiply by four final int idx = offset + (i << 2); - me[idx + 0] = (byte) (val[i] >> 24); + me[idx] = (byte) (val[i] >> 24); me[idx + 1] = (byte) (val[i] >> 16); me[idx + 2] = (byte) (val[i] >> 8); me[idx + 3] = (byte) (val[i]); diff --git a/core/src/main/java/net/tomp2p/peers/Number640.java b/core/src/main/java/net/tomp2p/peers/Number640.java index 07a0c48b5..640aa58b3 100644 --- a/core/src/main/java/net/tomp2p/peers/Number640.java +++ b/core/src/main/java/net/tomp2p/peers/Number640.java @@ -203,7 +203,7 @@ public float floatValue() { public double doubleValue() { return (locationKey.doubleValue() * Math.pow(2, Number160.BITS * 3)) + (domainKey.doubleValue() * Math.pow(2, Number160.BITS * 2)) - + (contentKey.doubleValue() * Math.pow(2, Number160.BITS * 1)) + + (contentKey.doubleValue() * Math.pow(2, Number160.BITS)) + versionKey.doubleValue(); } diff --git a/core/src/main/java/net/tomp2p/utils/CacheMap.java b/core/src/main/java/net/tomp2p/utils/CacheMap.java index b32cedf1c..776e49316 100644 --- a/core/src/main/java/net/tomp2p/utils/CacheMap.java +++ b/core/src/main/java/net/tomp2p/utils/CacheMap.java @@ -81,7 +81,7 @@ public V putIfAbsent(final K key, final V value) { return super.put(key, value); } return super.get(key); - }; + } @Override protected boolean removeEldestEntry(final Map.Entry eldest) { diff --git a/nat/pom.xml b/nat/pom.xml index 33a7adc6d..c9c02c4a5 100644 --- a/nat/pom.xml +++ b/nat/pom.xml @@ -54,13 +54,6 @@ tomp2p-core ${project.version} - - - ${project.groupId} - tomp2p-replication - ${project.version} - test - @@ -69,6 +62,7 @@ 4.11 test + ${project.groupId} tomp2p-replication From 772ce407b4519ada9b797a1f574c9db8cf6d154e Mon Sep 17 00:00:00 2001 From: Esfomeado Date: Thu, 8 Oct 2015 16:03:32 +0100 Subject: [PATCH 090/135] Typo Fixes --- .../ChannelServerConfiguration.java | 2 +- .../java/net/tomp2p/connection/HeartBeat.java | 2 +- .../connection/IdleStateHandlerTomP2P.java | 2 +- .../net/tomp2p/connection/PeerConnection.java | 2 +- .../net/tomp2p/connection/RequestHandler.java | 2 +- .../net/tomp2p/connection/Reservation.java | 4 ++-- .../net/tomp2p/connection/SendBehavior.java | 2 +- .../net/tomp2p/connection/TimeoutFactory.java | 6 ++--- .../net/tomp2p/futures/BaseFutureImpl.java | 2 +- .../tomp2p/futures/BaseFutureListener.java | 2 +- .../java/net/tomp2p/futures/FutureDirect.java | 2 +- .../java/net/tomp2p/futures/FutureDone.java | 2 +- .../net/tomp2p/futures/FutureLateJoin.java | 6 ++--- .../net/tomp2p/futures/FutureLaterJoin.java | 8 +++---- .../net/tomp2p/futures/FutureProgres.java | 2 +- .../net/tomp2p/futures/FutureResponse.java | 10 ++++----- .../java/net/tomp2p/futures/FutureTask.java | 2 +- .../net/tomp2p/message/DSASignatureCodec.java | 8 +++---- .../main/java/net/tomp2p/message/Encoder.java | 4 ++-- .../main/java/net/tomp2p/message/Message.java | 2 +- .../net/tomp2p/message/TomP2POutbound.java | 2 +- .../java/net/tomp2p/message/TrackerData.java | 6 ++--- .../net/tomp2p/p2p/DistributedRouting.java | 4 ++-- .../java/net/tomp2p/p2p/MaintenanceTask.java | 10 ++++----- .../java/net/tomp2p/p2p/RoutingMechanism.java | 10 ++++----- .../net/tomp2p/p2p/builder/PingBuilder.java | 2 +- .../tomp2p/p2p/builder/RoutingBuilder.java | 2 +- .../java/net/tomp2p/peers/LocalMapConf.java | 20 ++++++++--------- .../main/java/net/tomp2p/peers/Number160.java | 2 +- .../java/net/tomp2p/peers/PeerAddress.java | 2 -- .../java/net/tomp2p/peers/PeerIPFilter.java | 2 +- .../main/java/net/tomp2p/peers/PeerMap.java | 10 ++++----- .../java/net/tomp2p/rpc/DispatchHandler.java | 2 +- core/src/main/java/net/tomp2p/rpc/RPC.java | 2 +- .../main/java/net/tomp2p/rpc/RPCUtils.java | 4 ++-- .../storage/AlternativeCompositeByteBuf.java | 2 +- .../src/main/java/net/tomp2p/utils/Utils.java | 10 ++++----- .../net/tomp2p/dht/DistributedHashTable.java | 4 ++-- .../main/java/net/tomp2p/dht/FutureDHT.java | 4 ++-- .../main/java/net/tomp2p/dht/FutureSend.java | 8 +++---- dht/src/main/java/net/tomp2p/dht/PeerDHT.java | 2 +- .../main/java/net/tomp2p/dht/PutBuilder.java | 8 +++---- .../java/net/tomp2p/dht/StorageLayer.java | 10 ++++----- .../java/net/tomp2p/dht/StorageMemory.java | 2 +- .../main/java/net/tomp2p/dht/StorageRPC.java | 2 +- .../net/tomp2p/examples/ExampleBootstrap.java | 2 +- .../tomp2p/examples/ExampleConsistency.java | 2 +- .../examples/ExampleDirectReplication.java | 4 ++-- .../examples/ExampleDomainProtection.java | 6 ++--- .../examples/ExampleIndirectReplication.java | 8 +++---- .../main/java/net/tomp2p/holep/HolePRPC.java | 2 +- .../main/java/net/tomp2p/holep/NATType.java | 2 +- .../net/tomp2p/holep/NATTypeDetection.java | 2 +- .../holep/strategy/AbstractHolePStrategy.java | 8 +++---- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 2 +- .../net/tomp2p/natpmp/MapRequestMessage.java | 4 ++-- .../main/java/net/tomp2p/natpmp/Message.java | 4 ++-- .../java/net/tomp2p/natpmp/MessageQueue.java | 4 ++-- .../net/tomp2p/relay/DistributedRelay.java | 2 +- .../main/java/net/tomp2p/relay/Forwarder.java | 6 ++--- .../main/java/net/tomp2p/relay/RelayRPC.java | 4 ++-- .../java/net/tomp2p/relay/RelayUtils.java | 7 +++--- .../net/tomp2p/replication/Replication.java | 14 ++++++------ .../replication/ResponsibilityListener.java | 2 +- .../net/tomp2p/tracker/AddTrackerBuilder.java | 14 ++++++------ .../tomp2p/tracker/DistributedTracker.java | 14 ++++++------ .../net/tomp2p/tracker/FutureTracker.java | 2 +- .../net/tomp2p/tracker/GetTrackerBuilder.java | 16 +++++++------- .../tomp2p/tracker/PeerBuilderTracker.java | 6 ++--- .../tomp2p/tracker/TrackerConfiguration.java | 2 +- .../java/net/tomp2p/tracker/TrackerRPC.java | 6 ++--- .../net/tomp2p/tracker/TrackerStorage.java | 22 +++++++++---------- .../java/net/tomp2p/tracker/UtilsTracker.java | 2 +- 73 files changed, 185 insertions(+), 188 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java b/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java index f8bc5f68a..782022a2e 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java @@ -66,7 +66,7 @@ public boolean isBehindFirewall() { /** * @param behindFirewall - * Set to true if this peer is behind a firewall and not directly accessable + * Set to true if this peer is behind a firewall and not directly accessible * @return This class */ public ChannelServerConfiguration behindFirewall(final boolean behindFirewall) { diff --git a/core/src/main/java/net/tomp2p/connection/HeartBeat.java b/core/src/main/java/net/tomp2p/connection/HeartBeat.java index 535e2d044..a067a3f2a 100644 --- a/core/src/main/java/net/tomp2p/connection/HeartBeat.java +++ b/core/src/main/java/net/tomp2p/connection/HeartBeat.java @@ -99,7 +99,7 @@ public HeartBeat peerConnection(PeerConnection peerConnection) { @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { if (ctx.channel().isActive() && ctx.channel().isRegistered()) { - // channelActvie() event has been fired already, which means this.channelActive() will + // channelActive() event has been fired already, which means this.channelActive() will // not be invoked. We have to initialize here instead. initialize(ctx); } else { diff --git a/core/src/main/java/net/tomp2p/connection/IdleStateHandlerTomP2P.java b/core/src/main/java/net/tomp2p/connection/IdleStateHandlerTomP2P.java index a858aec3e..d911daaaf 100644 --- a/core/src/main/java/net/tomp2p/connection/IdleStateHandlerTomP2P.java +++ b/core/src/main/java/net/tomp2p/connection/IdleStateHandlerTomP2P.java @@ -67,7 +67,7 @@ public long getAllIdleTimeInMillis() { @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { if (ctx.channel().isActive() && ctx.channel().isRegistered()) { - // channelActvie() event has been fired already, which means this.channelActive() will + // channelActive() event has been fired already, which means this.channelActive() will // not be invoked. We have to initialize here instead. initialize(ctx); } else { diff --git a/core/src/main/java/net/tomp2p/connection/PeerConnection.java b/core/src/main/java/net/tomp2p/connection/PeerConnection.java index 1c557bf45..d224aca6e 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerConnection.java +++ b/core/src/main/java/net/tomp2p/connection/PeerConnection.java @@ -113,7 +113,7 @@ private void addCloseListener(final ChannelFuture channelFuture) { channelFuture.channel().closeFuture().addListener(new GenericFutureListener>() { @Override public void operationComplete(Future arg0) throws Exception { - LOG.debug("About to close the connection {}, {}.", channelFuture.channel(), initiator ? "initiator" : "from-disptacher"); + LOG.debug("About to close the connection {}, {}.", channelFuture.channel(), initiator ? "initiator" : "from-dispatcher"); closeFuture.done(); } }); diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index 903268631..fdb205f8d 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -255,7 +255,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo MessageID recvMessageID = new MessageID(responseMessage); // Error handling if (responseMessage.type() == Message.Type.UNKNOWN_ID) { - String msg = "Message was not delivered successfully, unknow ID (peer may be offline or unknown RPC handler): " + String msg = "Message was not delivered successfully, unknown ID (peer may be offline or unknown RPC handler): " + this.message; exceptionCaught(ctx, new PeerException(PeerException.AbortCause.PEER_ABORT, msg)); responseMessage.release(); diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 04480393a..c54ab34d4 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -204,7 +204,7 @@ public void operationComplete(final FutureDone future) throws Exception { */ public FutureChannelCreator createPermanent(final int permitsPermanentTCP) { if (permitsPermanentTCP > maxPermitsPermanentTCP) { - throw new IllegalArgumentException(String.format("Cannot acquire more permantent TCP connections (%s) than maximally allowed (%s).", permitsPermanentTCP, maxPermitsPermanentTCP)); + throw new IllegalArgumentException(String.format("Cannot acquire more permanent TCP connections (%s) than maximally allowed (%s).", permitsPermanentTCP, maxPermitsPermanentTCP)); } final FutureChannelCreator futureChannelCreator = new FutureChannelCreator(); read.lock(); @@ -275,7 +275,7 @@ public FutureDone shutdown() { // this is very important that we set first the listener and // then call shutdown. Otherwise, the order of // the listener calls is not guaranteed and we may call this - // listener before the semphore.release, + // listener before the semaphore.release, // causing an exception. channelCreator.shutdownFuture().addListener(new BaseFutureAdapter>() { @Override diff --git a/core/src/main/java/net/tomp2p/connection/SendBehavior.java b/core/src/main/java/net/tomp2p/connection/SendBehavior.java index 24d46f95b..daaa3458e 100644 --- a/core/src/main/java/net/tomp2p/connection/SendBehavior.java +++ b/core/src/main/java/net/tomp2p/connection/SendBehavior.java @@ -24,7 +24,7 @@ public enum SendMethod { /** * Open a reverse connection to the receiver and send the message. The - * reverse conneciton is closed afterwards. + * reverse connection is closed afterwards. */ RCON, diff --git a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java index b2c136910..9d61276bc 100644 --- a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java +++ b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java @@ -53,7 +53,7 @@ public class TimeoutFactory { /** * Creates a factory for timeout handlers. * @param futureResponse - * The future that will be called if a timeout occured + * The future that will be called if a timeout occurred * @param timeoutSeconds * The time for a timeout * @param peerStatusListeners @@ -104,11 +104,11 @@ private static class TimeHandler extends ChannelDuplexHandler { /** * @param futureResponse - * The future that will be called if a timeout occured. Can + * The future that will be called if a timeout occurred. Can * be null if we are server, if we are client, futureResponse * will be set * @param peerStatusListeners - * The listeners that get notified when a timeout happend + * The listeners that get notified when a timeout happened */ public TimeHandler(final FutureResponse futureResponse, final List peerStatusListeners, final String name) { diff --git a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java index 2fb8fe13c..386192f6e 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFutureImpl.java @@ -348,7 +348,7 @@ private void callOperationComplete(final BaseFutureListener listener) { listener.exceptionCaught(e); listener.operationComplete(this); } catch (final Exception e1) { - LOG.error("Unexcpected exception in exceptionCaught()", e1); + LOG.error("Unexpected exception in exceptionCaught()", e1); } } } diff --git a/core/src/main/java/net/tomp2p/futures/BaseFutureListener.java b/core/src/main/java/net/tomp2p/futures/BaseFutureListener.java index 95d30ef70..0cfa7919c 100644 --- a/core/src/main/java/net/tomp2p/futures/BaseFutureListener.java +++ b/core/src/main/java/net/tomp2p/futures/BaseFutureListener.java @@ -39,7 +39,7 @@ public interface BaseFutureListener { * @param t * The exception thrown in #operationComplete(BaseFuture). * @throws Exception - * If an execption is thrown, it is printed in the log and and + * If an exception is thrown, it is printed in the log and and * System.err */ public abstract void exceptionCaught(Throwable t) throws Exception; diff --git a/core/src/main/java/net/tomp2p/futures/FutureDirect.java b/core/src/main/java/net/tomp2p/futures/FutureDirect.java index f917b0736..05734dac0 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDirect.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDirect.java @@ -53,7 +53,7 @@ public boolean responseLater(Message responseMessage) { if(completed) { return false; } - reponseLater = true; + responseLater = true; if (responseMessage != null) { this.responseMessage = responseMessage; // if its ok or nok, the communication was successful. diff --git a/core/src/main/java/net/tomp2p/futures/FutureDone.java b/core/src/main/java/net/tomp2p/futures/FutureDone.java index cb1c61ddd..3a5284f0c 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDone.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDone.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** - * A generic future that can be used to set a future to complete with an attachement. + * A generic future that can be used to set a future to complete with an attachment. * * @author Thomas Bocek * diff --git a/core/src/main/java/net/tomp2p/futures/FutureLateJoin.java b/core/src/main/java/net/tomp2p/futures/FutureLateJoin.java index cc20cc8c9..4a43c7484 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureLateJoin.java +++ b/core/src/main/java/net/tomp2p/futures/FutureLateJoin.java @@ -35,7 +35,7 @@ public class FutureLateJoin extends BaseFutureImpl futuresDone; private final List futuresSubmitted; - private K lastSuceessFuture; + private K lastSuccessFuture; private int successCount = 0; @@ -89,7 +89,7 @@ public void operationComplete(final K future) throws Exception { if (!completed) { if (future.isSuccess()) { successCount++; - lastSuceessFuture = future; + lastSuccessFuture = future; } futuresDone.add(future); done = checkDone(); @@ -139,7 +139,7 @@ public List futuresDone() { */ public K lastSuceessFuture() { synchronized (lock) { - return lastSuceessFuture; + return lastSuccessFuture; } } diff --git a/core/src/main/java/net/tomp2p/futures/FutureLaterJoin.java b/core/src/main/java/net/tomp2p/futures/FutureLaterJoin.java index eec805022..2822e6025 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureLaterJoin.java +++ b/core/src/main/java/net/tomp2p/futures/FutureLaterJoin.java @@ -35,7 +35,7 @@ public class FutureLaterJoin extends BaseFutureImpl futuresDone() { /** * @return the last successful finished future. */ - public K lastSuceessFuture() { + public K lastSuccessFuture() { synchronized (lock) { - return lastSuceessFuture; + return lastSuccessFuture; } } } diff --git a/core/src/main/java/net/tomp2p/futures/FutureProgres.java b/core/src/main/java/net/tomp2p/futures/FutureProgres.java index 5cc23bb07..b6cb07b75 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureProgres.java +++ b/core/src/main/java/net/tomp2p/futures/FutureProgres.java @@ -17,7 +17,7 @@ package net.tomp2p.futures; /** - * A generic future that can be used to set a future to complete with an attachement. + * A generic future that can be used to set a future to complete with an attachment. * * @author Thomas Bocek * diff --git a/core/src/main/java/net/tomp2p/futures/FutureResponse.java b/core/src/main/java/net/tomp2p/futures/FutureResponse.java index 08397c3b8..f03ef25c5 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureResponse.java +++ b/core/src/main/java/net/tomp2p/futures/FutureResponse.java @@ -43,7 +43,7 @@ public class FutureResponse extends BaseFutureImpl { // the reply to this request protected Message responseMessage; - protected boolean reponseLater = false; + protected boolean responseLater = false; private final RTT roundTripTime = new RTT(); @@ -120,7 +120,7 @@ public boolean responseLater(final Message responseMessage) { } return false; } - reponseLater = true; + responseLater = true; if (responseMessage != null) { this.responseMessage = responseMessage; // if its ok or nok, the communication was successful. @@ -143,7 +143,7 @@ public boolean failedLater(final Throwable cause) { if(completed) { return false; } - reponseLater = true; + responseLater = true; this.reason = stringWriter.toString(); this.type = FutureType.FAILED; } @@ -152,7 +152,7 @@ public boolean failedLater(final Throwable cause) { public FutureResponse responseNow() { synchronized (lock) { - if (!reponseLater && !completed) { + if (!responseLater && !completed) { failed("No future set beforehand, probably an early shutdown / timeout, or use setFailedLater() or setResponseLater()"); return this; } @@ -165,7 +165,7 @@ public FutureResponse responseNow() { } protected boolean completedAndNotify() { - if (reponseLater) { + if (responseLater) { return false; } return super.completedAndNotify(); diff --git a/core/src/main/java/net/tomp2p/futures/FutureTask.java b/core/src/main/java/net/tomp2p/futures/FutureTask.java index d3f329580..e7efa1f06 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureTask.java +++ b/core/src/main/java/net/tomp2p/futures/FutureTask.java @@ -50,7 +50,7 @@ public FutureTask() { * were created after the routing process. * * @param futureResponse - * The futurRepsonse that has been created + * The futureResponse that has been created */ public void addRequests(FutureAsyncTask futureResponse) { synchronized (lock) { diff --git a/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java b/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java index bb0b8bc16..aba42c098 100644 --- a/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java +++ b/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java @@ -24,7 +24,7 @@ import net.tomp2p.utils.Utils; /** - * Bare minimun ASN.1 encoder and decoder for the signature. + * Bare minimum ASN.1 encoder and decoder for the signature. * * @author Thomas Bocek * @@ -47,14 +47,14 @@ public DSASignatureCodec(byte[] encodedData) throws IOException { } int seqLen = encodedData[1]; if (seqLen < 0) { - throw new IOException("cannot handle seq legth > than 127, got " + seqLen); + throw new IOException("cannot handle seq length > than 127, got " + seqLen); } if (encodedData[2] != 0x02) { throw new IOException("expected sequence with value 2, but got " + encodedData[2]); } int intLen1 = encodedData[3]; if (intLen1 < 0) { - throw new IOException("cannot handle int legth > than 127, got " + intLen1); + throw new IOException("cannot handle int length > than 127, got " + intLen1); } number1 = encodeNumber(encodedData, 4, intLen1); if (encodedData[4 + intLen1] != 0x02) { @@ -62,7 +62,7 @@ public DSASignatureCodec(byte[] encodedData) throws IOException { } int intLen2 = encodedData[5 + intLen1]; if (intLen2 < 0) { - throw new IOException("cannot handle int legth > than 127, got " + intLen2); + throw new IOException("cannot handle int length > than 127, got " + intLen2); } number2 = encodeNumber(encodedData, 6 + intLen1, intLen2); } diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index b57adadde..78302dda8 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -142,7 +142,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException break; case MAP_KEY640_DATA: DataMap dataMap = message.dataMap(next.index()); - // legnth + // length buf.writeInt(dataMap.size()); if (dataMap.isConvert()) { for (Entry entry : dataMap.dataMapConvert().entrySet()) { @@ -205,7 +205,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException if (buffer.incRead(readable) == buffer.length()) { message.contentReferences().poll(); } else if (message.isStreaming()) { - LOG.debug("Partial message of lengt {} sent.", readable); + LOG.debug("Partial message of length {} sent.", readable); return false; } else { final String description = "Larger buffer has been announced, but not in message streaming mode. This is wrong."; diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 300a8b1e9..76516e574 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -496,7 +496,7 @@ public Message hasContent(final boolean content) { // Types of requests /** - * @return True if this is a request, a regural or a fire and forget + * @return True if this is a request, a regular or a fire and forget */ public boolean isRequest() { return type == Type.REQUEST_1 || type == Type.REQUEST_2 || type == Type.REQUEST_3 || type == Type.REQUEST_4 diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index d2755d782..6cbcb49de 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -111,7 +111,7 @@ public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cau LOG.error("Exception in encoding when started.", cause); cause.printStackTrace(); } - //if exeception is not propagated, we may need to wait for the timeout - check testChangeEntryProtectionKey + //if exception is not propagated, we may need to wait for the timeout - check testChangeEntryProtectionKey super.exceptionCaught(ctx, cause); } } diff --git a/core/src/main/java/net/tomp2p/message/TrackerData.java b/core/src/main/java/net/tomp2p/message/TrackerData.java index ff5311e6e..53d9cc6bb 100644 --- a/core/src/main/java/net/tomp2p/message/TrackerData.java +++ b/core/src/main/java/net/tomp2p/message/TrackerData.java @@ -29,7 +29,7 @@ public class TrackerData { - private final static Data EMTPY_DATA = new Data(0, 0); + private final static Data EMPTY_DATA = new Data(0, 0); private final Map peerAddresses; @@ -74,8 +74,8 @@ public int size() { return peerAddresses.size(); } - public void put(PeerAddress remotePeer, Data attachement) { - peerAddresses.put(remotePeer, attachement == null ? EMTPY_DATA : attachement); + public void put(PeerAddress remotePeer, Data attachment) { + peerAddresses.put(remotePeer, attachment == null ? EMPTY_DATA : attachment); } public Map.Entry remove(Number160 remotePeerId) { diff --git a/core/src/main/java/net/tomp2p/p2p/DistributedRouting.java b/core/src/main/java/net/tomp2p/p2p/DistributedRouting.java index 11a633074..b50442095 100644 --- a/core/src/main/java/net/tomp2p/p2p/DistributedRouting.java +++ b/core/src/main/java/net/tomp2p/p2p/DistributedRouting.java @@ -213,7 +213,7 @@ private FutureRouting routing(final Collection peerAddresses, } else if (type == Type.REQUEST_3 && !randomSearch && peerBean.digestTracker() != null) { DigestInfo digestInfo = peerBean.digestTracker().digest(routingBuilder.locationKey(), routingBuilder.domainKey(), routingBuilder.contentKey()); - // we always put ourselfs to the tracker list, so we need to check + // we always put ourselves to the tracker list, so we need to check // if we know also other peers on our trackers. if (digestInfo.size() > 0) { directHits.put(peerBean.serverPeerAddress(), digestInfo); @@ -234,7 +234,7 @@ private FutureRouting routing(final Collection peerAddresses, // if a peer bootstraps to itself, then the size of peerAddresses // is 1 and it contains itself. Check for that because we need to // know if we are routing, bootstrapping and bootstrapping to - // ourselfs, to return the correct status for the future + // ourselves, to return the correct status for the future boolean isRoutingOnlyToSelf = (peerAddresses.size() == 1 && peerAddresses.iterator().next() .peerAddress().equals(peerBean.serverPeerAddress())); routingBuilder.routingOnlyToSelf(isRoutingOnlyToSelf); diff --git a/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java b/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java index 0430b53d3..95a6cc688 100644 --- a/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java +++ b/core/src/main/java/net/tomp2p/p2p/MaintenanceTask.java @@ -52,15 +52,15 @@ public void run() { return; } for (Maintainable maintainable : maintainables) { - PeerStatistic peerStatatistic = maintainable.nextForMaintenance(runningFutures.values()); - if(peerStatatistic == null) { + PeerStatistic peerStatistic = maintainable.nextForMaintenance(runningFutures.values()); + if(peerStatistic == null) { continue; } - BaseFuture future = peer.ping().peerAddress(peerStatatistic.peerAddress()).start(); - LOG.debug("Maintenance ping from {} to {}.", peer.peerAddress(), peerStatatistic.peerAddress()); + BaseFuture future = peer.ping().peerAddress(peerStatistic.peerAddress()).start(); + LOG.debug("Maintenance ping from {} to {}.", peer.peerAddress(), peerStatistic.peerAddress()); peer.notifyAutomaticFutures(future); - runningFutures.put(future, peerStatatistic.peerAddress()); + runningFutures.put(future, peerStatistic.peerAddress()); COUNTER.incrementAndGet(); future.addListener(new BaseFutureAdapter() { @Override diff --git a/core/src/main/java/net/tomp2p/p2p/RoutingMechanism.java b/core/src/main/java/net/tomp2p/p2p/RoutingMechanism.java index 6c6e8af1e..063ac55ef 100644 --- a/core/src/main/java/net/tomp2p/p2p/RoutingMechanism.java +++ b/core/src/main/java/net/tomp2p/p2p/RoutingMechanism.java @@ -64,7 +64,7 @@ public class RoutingMechanism { * @param futureResponses * The current future responses that are running * @param futureRoutingResponse - * The reponse future from this routing request + * The response future from this routing request */ public RoutingMechanism(final AtomicReferenceArray futureResponses, final FutureRouting futureRoutingResponse, final Collection peerMapFilters) { @@ -210,12 +210,12 @@ public void maxFailures(int maxFailures) { this.maxFailures = maxFailures; } - public int maxSucess() { + public int maxSuccess() { return maxSuccess; } - public void maxSucess(int maxSucess) { - this.maxSuccess = maxSucess; + public void maxSuccess(int maxSuccess) { + this.maxSuccess = maxSuccess; } public PeerAddress pollFirstInQueueToAsk() { @@ -292,7 +292,7 @@ public boolean evaluateSuccess(PeerAddress remotePeer, DigestInfo digestBean, LOG.debug("Enough direct hits found: {}.", directHits); finished = true; stopCreatingNewFutures = true; - } else if ((++nrSuccess) > maxSucess()) { + } else if ((++nrSuccess) > maxSuccess()) { // wait until pending futures are finished LOG.debug("Max success reached: {}.", nrSuccess); finished = last; diff --git a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java index 80a4f962e..4b262217b 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java @@ -246,7 +246,7 @@ public void operationComplete(FutureChannelCreator future) throws Exception { FutureResponse validBroadcast = peer.pingRPC().pingBroadcastUDP( peerAddress, future.channelCreator(), connectionConfiguration); if (!futureLateJoin.add(validBroadcast)) { - // the latejoin future is fininshed if the add returns false + // the latejoin future is finished if the add returns false break; } } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/RoutingBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/RoutingBuilder.java index 381dc561a..0ad033b1c 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/RoutingBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/RoutingBuilder.java @@ -192,7 +192,7 @@ public RoutingMechanism createRoutingMechanism(FutureRouting futureRouting) { routingMechanism.maxDirectHits(maxDirectHits()); routingMechanism.maxFailures(maxFailures()); routingMechanism.maxNoNewInfo(maxNoNewInfo()); - routingMechanism.maxSucess(maxSuccess()); + routingMechanism.maxSuccess(maxSuccess()); return routingMechanism; } diff --git a/core/src/main/java/net/tomp2p/peers/LocalMapConf.java b/core/src/main/java/net/tomp2p/peers/LocalMapConf.java index 79ad4b261..abaa58d26 100644 --- a/core/src/main/java/net/tomp2p/peers/LocalMapConf.java +++ b/core/src/main/java/net/tomp2p/peers/LocalMapConf.java @@ -2,20 +2,20 @@ public class LocalMapConf { - private int localMapTimout = Integer.MAX_VALUE; + private int localMapTimeout = Integer.MAX_VALUE; private int localMapSize = 1000; private int localMapRevTimeout = Integer.MAX_VALUE; private int localMapRevSize = 1000; - private int offlineMapTimout = 60; + private int offlineMapTimeout = 60; private int offlineMapSize = 1000; private int[] intervalSeconds = new int[] { 2, 4, 8, 16, 32, 64 }; - public int localMapTimout() { - return localMapTimout; + public int localMapTimeout() { + return localMapTimeout; } - public LocalMapConf localMapTimout(int localMapTimout) { - this.localMapTimout = localMapTimout; + public LocalMapConf localMapTimeout(int localMapTimout) { + this.localMapTimeout = localMapTimout; return this; } @@ -46,12 +46,12 @@ public LocalMapConf localMapRevSize(int localMapRevSize) { return this; } - public int offlineMapTimout() { - return offlineMapTimout; + public int offlineMapTimeout() { + return offlineMapTimeout; } - public LocalMapConf offlineMapTimout(int offlineMapTimout) { - this.offlineMapTimout = offlineMapTimout; + public LocalMapConf offlineMapTimeout(int offlineMapTimeout) { + this.offlineMapTimeout = offlineMapTimeout; return this; } diff --git a/core/src/main/java/net/tomp2p/peers/Number160.java b/core/src/main/java/net/tomp2p/peers/Number160.java index 1afd38bdd..5b6a524f6 100644 --- a/core/src/main/java/net/tomp2p/peers/Number160.java +++ b/core/src/main/java/net/tomp2p/peers/Number160.java @@ -151,7 +151,7 @@ public Number160(final byte[] val) { } /** - * Creates a new Key using the byte array. The array is copied to the backing int[] starting at the given offest. + * Creates a new Key using the byte array. The array is copied to the backing int[] starting at the given offset. * * @param val * byte array diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 17f43641e..83db380e1 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -32,8 +32,6 @@ import java.util.Collection; import java.util.Collections; -import javax.management.RuntimeErrorException; - import net.tomp2p.utils.Utils; /** diff --git a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java index 4629f1767..261a1a34a 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java +++ b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java @@ -22,7 +22,7 @@ /** * Filter peers if the IP is the same. TODO: make subnetting configurable, IPv4 - * and IPv6. Beeing too strict does not mean to harm the network. Other peers + * and IPv6. Being too strict does not mean to harm the network. Other peers * will have the information about the peer even if you excluded it. * * @author Thomas Bocek diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index 470ed77dc..19bfcbcf1 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -342,13 +342,13 @@ public boolean peerFound(PeerAddress remotePeer, final PeerAddress referrer, fin return true; } else if (old != null && !old.element1()) { LOG.debug("Unreliable information, don't update"); - //don't update, as we have second hand information that is not reliabel, we arleady have it, don't update + //don't update, as we have second hand information that is not reliabel, we already have it, don't update return false; } else { if (firstHand || (secondHand && !peerVerification)) { final Map map = peerMapVerified.get(classMember); - boolean insterted = false; + boolean inserted = false; synchronized (map) { // check again, now we are synchronized if (map.containsKey(remotePeer.peerId())) { @@ -359,11 +359,11 @@ public boolean peerFound(PeerAddress remotePeer, final PeerAddress referrer, fin peerStatistic.successfullyChecked(); peerStatistic.addRTT(roundTripTime); map.put(remotePeer.peerId(), peerStatistic); - insterted = true; + inserted = true; } } - if (insterted) { + if (inserted) { // if we inserted into the verified map, remove it from the non-verified map final Map mapOverflow = peerMapOverflow.get(classMember); synchronized (mapOverflow) { @@ -874,7 +874,7 @@ private static boolean updatePeerStatistic(final PeerAddress remotePeer, * (e.g. port) may have changed. * * @param tmp - * The map where the peer is suppost to be + * The map where the peer is supposed to be * @param peerAddress * The address of the peer that may have been changed * @param firstHand diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index f6c1251b2..e13ad1aae 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -129,7 +129,7 @@ public Message createResponseMessage(final Message requestMessage, final Type re public static Message createResponseMessage(final Message requestMessage, final Type replyType, final PeerAddress peerAddress) { Message replyMessage = new Message(); - // this will have the ports > 40'000 that we need to know for sendig the reply + // this will have the ports > 40'000 that we need to know for sending the reply replyMessage.senderSocket(requestMessage.senderSocket()); replyMessage.recipientSocket(requestMessage.recipientSocket()); replyMessage.recipient(requestMessage.sender()); diff --git a/core/src/main/java/net/tomp2p/rpc/RPC.java b/core/src/main/java/net/tomp2p/rpc/RPC.java index 3fb743a1c..d83e5aac6 100644 --- a/core/src/main/java/net/tomp2p/rpc/RPC.java +++ b/core/src/main/java/net/tomp2p/rpc/RPC.java @@ -1,7 +1,7 @@ package net.tomp2p.rpc; public class RPC { - //Max. 255 Commands - don't change the order!! keep .NET interoperatibility in mind + //Max. 255 Commands - don't change the order!! keep .NET interoperability in mind public enum Commands{ PING(), PUT(), diff --git a/core/src/main/java/net/tomp2p/rpc/RPCUtils.java b/core/src/main/java/net/tomp2p/rpc/RPCUtils.java index 9a64cf062..cb143ed73 100644 --- a/core/src/main/java/net/tomp2p/rpc/RPCUtils.java +++ b/core/src/main/java/net/tomp2p/rpc/RPCUtils.java @@ -15,7 +15,7 @@ public static byte[] toByteArray(BitSet bitSet) { if (bitSet.get(i)) { //big endian //bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8); - //litle endian + //little endian bytes[i/8] |= 1 << (7 - i % 8); } } @@ -33,7 +33,7 @@ public static BitSet fromByteArray(byte[] bytes) { for (int i = 0; i < bytes.length * 8; i++) { //big endian //if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) { - //litle endian + //little endian if ((bytes[i/8] & (1 << (7 - i % 8))) > 0) { bits.set(i); } diff --git a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java index 666c79d5e..71fbb670d 100644 --- a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java +++ b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java @@ -1476,7 +1476,7 @@ private void setComponentWriterIndex(int writerIndex) { } int index = findIndex(writerIndex); if(index < 0) { - //no component found, make sure we can write, thus adding a compontent. TODO: check fillbuffer + //no component found, make sure we can write, thus adding a component. TODO: check fillbuffer ensureWritable(writerIndex); index = findIndex(writerIndex); } diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index e78487f20..cfd8848b2 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -663,7 +663,7 @@ public static void nullCheck(Object... objects) { int counter = 0; for (Object object : objects) { if (object == null) { - throw new IllegalArgumentException("Null not allowed in paramenetr nr. " + counter); + throw new IllegalArgumentException("Null not allowed in parameter nr. " + counter); } counter++; } @@ -784,7 +784,7 @@ public static byte createByte(final BitSet bitSet) { } /** - * Adds a listener to the response futures and releases all aquired channels in the channel creator. + * Adds a listener to the response futures and releases all acquired channels in the channel creator. * * @param channelCreator * The channel creator that will be shutdown and all connections will be closed @@ -962,11 +962,11 @@ public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress * @return socketAddress */ public static PeerSocketAddress extractRandomRelay(final Message message) { - Object[] relayInetAdresses = message.recipient().peerSocketAddresses().toArray(); + Object[] relayInetAddresses = message.recipient().peerSocketAddresses().toArray(); PeerSocketAddress socketAddress = null; - if (relayInetAdresses.length > 0) { + if (relayInetAddresses.length > 0) { // we should be fair and choose one of the relays randomly - socketAddress = (PeerSocketAddress) relayInetAdresses[randomPositiveInt(relayInetAdresses.length)]; + socketAddress = (PeerSocketAddress) relayInetAddresses[randomPositiveInt(relayInetAddresses.length)]; } else { throw new IllegalArgumentException( "There are no PeerSocketAdresses available for this relayed Peer. This should not be possible!"); diff --git a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java index 773736605..b4da7eb5d 100644 --- a/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java +++ b/dht/src/main/java/net/tomp2p/dht/DistributedHashTable.java @@ -60,7 +60,7 @@ public class DistributedHashTable { private static final NavigableSet EMPTY_NAVIGABLE_SET = new TreeSet(); public static final int REASON_CANCEL = 254; - public static final int REASON_UNKOWN = 255; + public static final int REASON_UNKNOWN = 255; private final DistributedRouting routing; @@ -268,7 +268,7 @@ public void interMediateResponse(final FutureResponse future) { rawData.put(future.request().recipient(), error); } else { logger.debug("future failed: "+future.failedReason()); - Map error = Utils.setMapError(future.request().dataMap(0).dataMap(), (byte) REASON_UNKOWN); + Map error = Utils.setMapError(future.request().dataMap(0).dataMap(), (byte) REASON_UNKNOWN); rawData.put(future.request().recipient(), error); } } diff --git a/dht/src/main/java/net/tomp2p/dht/FutureDHT.java b/dht/src/main/java/net/tomp2p/dht/FutureDHT.java index a31acb732..0268d9f14 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureDHT.java @@ -63,7 +63,7 @@ public FutureForkJoin futureRequests() { * Adds all requests that have been created for the DHT operations. Those were created after the routing process. * * @param futureResponse - * The futurRepsonse that has been created + * The futureResponse that has been created */ public K addRequests(final FutureResponse futureResponse) { synchronized (lock) { @@ -79,7 +79,7 @@ public List requests() { } /** - * Adds a listener to the response future and releases all aquired channels in channel creator. + * Adds a listener to the response future and releases all acquired channels in channel creator. * * @param channelCreator * The channel creator that will be shutdown and all connections will be closed diff --git a/dht/src/main/java/net/tomp2p/dht/FutureSend.java b/dht/src/main/java/net/tomp2p/dht/FutureSend.java index 43111cdd0..a0263f11f 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureSend.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureSend.java @@ -120,9 +120,9 @@ public void directData2(final Map rawObjects, FutureDone rawDirectData1() { synchronized (lock) { @@ -131,9 +131,9 @@ public Map rawDirectData1() { } /** - * Return raw data from send_dircet (Object). + * Return raw data from send_direct (Object). * - * @return The raw data from send_dircet and the information which peer has been contacted + * @return The raw data from send_direct and the information which peer has been contacted */ public Map rawDirectData2() { synchronized (lock) { diff --git a/dht/src/main/java/net/tomp2p/dht/PeerDHT.java b/dht/src/main/java/net/tomp2p/dht/PeerDHT.java index 9d6fc294d..1b6522d45 100644 --- a/dht/src/main/java/net/tomp2p/dht/PeerDHT.java +++ b/dht/src/main/java/net/tomp2p/dht/PeerDHT.java @@ -90,7 +90,7 @@ public ParallelRequestBuilder parallelRequest(Number160 locationKey) { return new ParallelRequestBuilder>(this, locationKey); } - // ----- convenicence methods ------ + // ----- convenience methods ------ public BaseFuture shutdown() { return peer.shutdown(); } diff --git a/dht/src/main/java/net/tomp2p/dht/PutBuilder.java b/dht/src/main/java/net/tomp2p/dht/PutBuilder.java index 29cece373..58132eafc 100644 --- a/dht/src/main/java/net/tomp2p/dht/PutBuilder.java +++ b/dht/src/main/java/net/tomp2p/dht/PutBuilder.java @@ -39,7 +39,7 @@ public class PutBuilder extends DHTBuilder { private boolean putMeta = false; - private boolean putConfim = false; + private boolean putConfirm = false; private PublicKey changePublicKey = null; @@ -175,11 +175,11 @@ public PutBuilder putMeta() { } public boolean isPutConfirm() { - return putConfim; + return putConfirm; } public PutBuilder putConfirm() { - this.putConfim = true; + this.putConfirm = true; return this; } @@ -205,7 +205,7 @@ public FuturePut start() { } dataMap().put(data().getKey(), data().getValue()); } - if (!putMeta && !putConfim && dataMap == null && dataMapConvert == null) { + if (!putMeta && !putConfirm && dataMap == null && dataMapConvert == null) { throw new IllegalArgumentException( "You must either set data via setDataMap() or setData(). Cannot add nothing."); } diff --git a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java index 676f32fbd..87d075888 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageLayer.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageLayer.java @@ -65,13 +65,13 @@ public enum PutStatus { // Hash of public key is always preferred private ProtectionMode protectionDomainMode = ProtectionMode.MASTER_PUBLIC_KEY; - // Domains can generallay be protected + // Domains can generally be protected private ProtectionEnable protectionDomainEnable = ProtectionEnable.ALL; // Hash of public key is always preferred private ProtectionMode protectionEntryMode = ProtectionMode.MASTER_PUBLIC_KEY; - // Entries can generallay be protected + // Entries can generally be protected private ProtectionEnable protectionEntryEnable = ProtectionEnable.ALL; // stores the domains that cannot be reserved and items can be added by @@ -199,7 +199,7 @@ public Map> putAll(final NavigableMap dataMa continue; } - // We need this check in case we did not use the encoder/deconder, + // We need this check in case we did not use the encoder/decoder, // which is the case if we send the message to ourself. In that // case, the public key of the data is never set to the message // publick key, if the publick key of the data was null. @@ -689,7 +689,7 @@ private boolean securityDomainCheck(Number320 key, PublicKey publicKey, PublicKe // I dont want to claim the domain if (!domainProtection) { LOG.debug("no domain protection requested {} for domain {}", Utils.hash(newPublicKey), key); - // returns true if the domain is not protceted by others, otherwise + // returns true if the domain is not protected by others, otherwise // false if the domain is protected return !domainProtectedByOthers; } else { @@ -711,7 +711,7 @@ private boolean securityEntryCheck(Number480 key, PublicKey publicKeyMessage, Pu boolean entryProtectedByOthers = backend.isEntryProtectedByOthers(key, publicKeyMessage); // I dont want to claim the domain if (!entryProtection) { - // returns true if the domain is not protceted by others, otherwise + // returns true if the domain is not protected by others, otherwise // false if the domain is protected return !entryProtectedByOthers; } else { diff --git a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java index 44f263865..73ec48991 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageMemory.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageMemory.java @@ -225,7 +225,7 @@ public void removeResponsibility(Number160 locationKey) { Number160 peerId = responsibilityMap.remove(locationKey); if(peerId != null) { removeRevResponsibility(peerId, locationKey); - LOG.debug("Remove responsiblity for {}.", locationKey); + LOG.debug("Remove responsibility for {}.", locationKey); } } diff --git a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java index b77c24063..74a146e46 100644 --- a/dht/src/main/java/net/tomp2p/dht/StorageRPC.java +++ b/dht/src/main/java/net/tomp2p/dht/StorageRPC.java @@ -660,7 +660,7 @@ public void handleResponse(final Message message, PeerConnection peerConnection, final Message responseMessage = createResponseMessage(message, Type.OK); - //switch/case does not work here out of the box, need to convert byte back to enum, not sure if thats worth it. + //switch/case does not work here out of the box, need to convert byte back to enum, not sure if that's worth it. if (message.command() == RPC.Commands.ADD.getNr()) { handleAdd(message, responseMessage, isDomainProtected(message)); } else if(message.command() == RPC.Commands.PUT.getNr() || message.command() == RPC.Commands.REPLICA_PUT.getNr()) { diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleBootstrap.java b/examples/src/main/java/net/tomp2p/examples/ExampleBootstrap.java index df4bfe86b..f0909ba8f 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleBootstrap.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleBootstrap.java @@ -48,7 +48,7 @@ public static void main(String[] args) throws IOException, InterruptedException futureBootstrap1.awaitUninterruptibly(); System.out.println("peer[0] knows: " + peers[0].peerBean().peerMap().all() + " unverified: " + peers[0].peerBean().peerMap().allOverflow()); - System.out.println("wait for maintenace ping"); + System.out.println("wait for maintenance ping"); Thread.sleep(2000); System.out.println("peer[0] knows: " + peers[0].peerBean().peerMap().all() + " unverified: " + peers[0].peerBean().peerMap().allOverflow()); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleConsistency.java b/examples/src/main/java/net/tomp2p/examples/ExampleConsistency.java index c85ec2c63..0ae85ac17 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleConsistency.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleConsistency.java @@ -187,7 +187,7 @@ private static void exampleAttack(final Number160 key1, final PeerDHT[] peers) t //mpeer3.getPeerBean().storage() // .put(key, new Data("attack, attack, attack!"), null, false, false); - //wait for mainenance pings + //wait for maintenance pings Thread.sleep(3000); // we got attack! diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleDirectReplication.java b/examples/src/main/java/net/tomp2p/examples/ExampleDirectReplication.java index 6b1be2d5b..e47a5edfe 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleDirectReplication.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleDirectReplication.java @@ -58,7 +58,7 @@ public static void main(final String[] args) throws Exception { final int port = 4001; peers = ExampleUtils.createAndAttachPeersDHT(nrPeers, port); ExampleUtils.bootstrap(peers); - exmpleDirectReplication(peers); + exampleDirectReplication(peers); } finally { if (peers != null && peers[0] != null) { peers[0].shutdown(); @@ -75,7 +75,7 @@ public static void main(final String[] args) throws Exception { * @throws InterruptedException * @throws IOException . */ - private static void exmpleDirectReplication(final PeerDHT[] peers) throws IOException, InterruptedException { + private static void exampleDirectReplication(final PeerDHT[] peers) throws IOException, InterruptedException { PutBuilder putBuilder = peers[1].put(Number160.ONE).data(new Data("test")); JobScheduler replication = new JobScheduler(peers[1].peer()); Shutdown shutdown = replication.start(putBuilder, 1000, -1, new AutomaticFuture() { diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleDomainProtection.java b/examples/src/main/java/net/tomp2p/examples/ExampleDomainProtection.java index 66442592c..f6e759847 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleDomainProtection.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleDomainProtection.java @@ -52,12 +52,12 @@ public static void exampleAllMaster() futurePut = peer3.put( Number160.ONE ).data( new Data( "hello" ) ).domainKey( peer2Owner ).protectDomain().start(); futurePut.awaitUninterruptibly(); - System.out.println( "stored: " + futurePut.isSuccess() + " -> becaues peer1 already claimed this domain" ); + System.out.println( "stored: " + futurePut.isSuccess() + " -> because peer1 already claimed this domain" ); // peer 2 claims this domain futurePut = peer2.put( Number160.ONE ).data( new Data( "MINE!" ) ).domainKey( peer2Owner ).protectDomain().start(); futurePut.awaitUninterruptibly(); - System.out.println( "stored: " + futurePut.isSuccess() + " -> becaues peer2 is the owner" ); + System.out.println( "stored: " + futurePut.isSuccess() + " -> because peer2 is the owner" ); // get the data! FutureGet futureGet = peer1.get( Number160.ONE ).domainKey( peer2Owner ).start(); futureGet.awaitUninterruptibly(); @@ -96,7 +96,7 @@ public static void exampleNoneMaster() futurePut = peer2.put( Number160.ONE ).data( new Data( "MINE!" ) ).protectDomain().domainKey( peer2Owner ).start(); futurePut.awaitUninterruptibly(); - System.out.println( "stored: " + futurePut.isSuccess() + " -> becaues peer2 is the owner" ); + System.out.println( "stored: " + futurePut.isSuccess() + " -> because peer2 is the owner" ); // get the data! FutureGet futureGet = peer1.get( Number160.ONE ).domainKey( peer2Owner ).start(); futureGet.awaitUninterruptibly(); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleIndirectReplication.java b/examples/src/main/java/net/tomp2p/examples/ExampleIndirectReplication.java index ec36b6218..b629803e5 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleIndirectReplication.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleIndirectReplication.java @@ -54,7 +54,7 @@ private ExampleIndirectReplication() { * @throws Exception . */ public static void main(final String[] args) throws Exception { - exmpleIndirectReplication(); + exampleIndirectReplication(); } /** @@ -64,7 +64,7 @@ public static void main(final String[] args) throws Exception { * @throws IOException . * @throws InterruptedException . */ - private static void exmpleIndirectReplication() throws IOException, InterruptedException { + private static void exampleIndirectReplication() throws IOException, InterruptedException { final int port1 = 4001; final int nr1 = 1; final int port2 = 4002; @@ -104,14 +104,14 @@ private static void exmpleIndirectReplication() throws IOException, InterruptedE //the result shows in the command line 1, 1, 1. This behavior is explaind as follows: // //The bootstrap from peer1 to peer2 causes peer 1 to replicate the data object to peer2 - //The bootstrap from peer1 to peer3 causes the peer3 to become the new resposible peer. Thus, peer1 + //The bootstrap from peer1 to peer3 causes the peer3 to become the new responsible peer. Thus, peer1 //transfers the data to peer3 and all three peers have the data. // //Now consider the following scenario, if we change the order of the bootstrap, so that peer1 first //bootstraps to peer3 and then to peer2, we will see 1, 0, 1 in the command line. This behavior is explained //as follows: // - //First peer1 will figure out that peer3 is repsonsible and transfer the data to this peer. Then peer1 bootstraps to + //First peer1 will figure out that peer3 is responsible and transfer the data to this peer. Then peer1 bootstraps to //peer2. However, as peer1 is not responsible anymore and peer3 does not know yet peer2, peer 2 won't see that data //until peer3 does the periodical replication check. shutdown(peers); diff --git a/nat/src/main/java/net/tomp2p/holep/HolePRPC.java b/nat/src/main/java/net/tomp2p/holep/HolePRPC.java index f11ac17d9..e52ca2c54 100644 --- a/nat/src/main/java/net/tomp2p/holep/HolePRPC.java +++ b/nat/src/main/java/net/tomp2p/holep/HolePRPC.java @@ -110,7 +110,7 @@ private void forwardHolePunchMessage(final Message message, final Responder resp public void operationComplete(final FutureDone future) throws Exception { if (future.isSuccess()) { final Message answerMessage = createAnswerMessage(message, future.object()); - LOG.debug("Returing from relay to requester: {}", answerMessage); + LOG.debug("Returning from relay to requester: {}", answerMessage); responder.response(answerMessage); } else { responder.failed(Type.EXCEPTION, "Relaying message failed: " + future.failedReason()); diff --git a/nat/src/main/java/net/tomp2p/holep/NATType.java b/nat/src/main/java/net/tomp2p/holep/NATType.java index aa066a4d1..2aa554979 100644 --- a/nat/src/main/java/net/tomp2p/holep/NATType.java +++ b/nat/src/main/java/net/tomp2p/holep/NATType.java @@ -47,7 +47,7 @@ public HolePStrategy holePuncher(final Peer peer, int numberOfHoles, final int i }, /** * NON_PRESERVING_SEQUENTIAL means, that a NAT will assign port number to - * its public endpoint in an continous increasing manner (e.g. 1234). + * its public endpoint in an continuous increasing manner (e.g. 1234). */ NON_PRESERVING_SEQUENTIAL { @Override diff --git a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java index 1e885c729..f00b5278f 100644 --- a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java +++ b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java @@ -32,7 +32,7 @@ public static FutureDone checkNATType(final Peer peer, final PeerAddres /** * This method contacts a Relay {@link Peer} in order to find out the NAT - * port assignement behavior. This assumes that you are behind a NAT as + * port assignment behavior. This assumes that you are behind a NAT as * discovered with Peer.discover(). If you are not behind NAT, then this * will return PORT_PRESERVING. There are 3 possible NAT behaviours:
* PORT_PRESERVING = The NAT preserves the port which a peer uses to send diff --git a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java index 358ee15f2..1193e9628 100644 --- a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java +++ b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java @@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory; /** - * DO NOT INSTANCIATE THIS CLASS!
+ * DO NOT INSTANTIATE THIS CLASS!
*
* * If you need to add a new supported nat type please extend this class and @@ -354,7 +354,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message msg) final int numberOfConnectionAttempts = portList.size() / 2; final AtomicInteger countDown = new AtomicInteger(numberOfConnectionAttempts); for (int i = 0; i < portList.size(); i++) { - // this ensures, that if all hole punch attemps fail, + // this ensures, that if all hole punch attempts fail, // the system is still able to send the message via // relaying without the user noticing it final FutureResponse holePFutureResponse = handleFutureResponse(originalFutureResponse, portList, i, countDown, @@ -374,9 +374,9 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message msg) } /** - * this ensures, that if all hole punch attemps fail, the system is + * this ensures, that if all hole punch attempts fail, the system is * still able to send the message via relaying without the user - * noticing it. In case of a succesful transmission, it also + * noticing it. In case of a successful transmission, it also * forwards the response message to the original FutureResponse. * * @param originalFutureResponse diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index ddd6eff09..92dc4ca89 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -350,7 +350,7 @@ private void checkRconPreconditions(final PeerAddress relayPeerAddress, final Pe // reverse connection setup. It just doesn't make sense! if (peer.peerAddress().peerId().equals(relayPeerAddress.peerId())) { throw new IllegalStateException( - "We are alredy a relay for the target peer. We shouldn't use a reverse connection to connect to the targeted peer!"); + "We are already a relay for the target peer. We shouldn't use a reverse connection to connect to the targeted peer!"); } } diff --git a/nat/src/main/java/net/tomp2p/natpmp/MapRequestMessage.java b/nat/src/main/java/net/tomp2p/natpmp/MapRequestMessage.java index 80c7781bc..c8a27387b 100644 --- a/nat/src/main/java/net/tomp2p/natpmp/MapRequestMessage.java +++ b/nat/src/main/java/net/tomp2p/natpmp/MapRequestMessage.java @@ -137,7 +137,7 @@ public int getRequestedExternalPort() { * @return The external port that was assigned. * @throws NatPmpException * Thrown if there was an exception generated during the parsing - * of the respnse. + * of the response. */ public Integer getExternalPort() throws NatPmpException { return externalPort; @@ -158,7 +158,7 @@ public int getRequestedPortMappingLifetime() { * @return The assigned port mapping lifetime, in seconds. * @throws NatPmpException * Thrown if there was an exception generated during the parsing - * of the respnse. + * of the response. */ public Integer getPortMappingLifetime() throws NatPmpException { return portMappingLifetime; diff --git a/nat/src/main/java/net/tomp2p/natpmp/Message.java b/nat/src/main/java/net/tomp2p/natpmp/Message.java index 958bdb2f8..26088b73e 100644 --- a/nat/src/main/java/net/tomp2p/natpmp/Message.java +++ b/nat/src/main/java/net/tomp2p/natpmp/Message.java @@ -54,7 +54,7 @@ public abstract class Message { private Integer secondsSinceEpoch; /** - * Constructs a new Message with the speficied type. + * Constructs a new Message with the specified type. * * @param type * The {@link MessageType} of the message. This must not be null. @@ -98,7 +98,7 @@ public abstract class Message { abstract void parseResponse(byte[] response) throws Exception; /** - * Gets the excpetion associated with the response. This exception is + * Gets the exception associated with the response. This exception is * generally provided by an external entity. * * @return The {@link NatPmpException} associated with the response. diff --git a/nat/src/main/java/net/tomp2p/natpmp/MessageQueue.java b/nat/src/main/java/net/tomp2p/natpmp/MessageQueue.java index 411a6a359..078f9aa72 100644 --- a/nat/src/main/java/net/tomp2p/natpmp/MessageQueue.java +++ b/nat/src/main/java/net/tomp2p/natpmp/MessageQueue.java @@ -62,7 +62,7 @@ private MessageQueue(InetAddress gatewayIP) { } /** - * Creates and starts a {@link MessageQueue}. The created MesageQueue is + * Creates and starts a {@link MessageQueue}. The created MessageQueue is * returned. To use the queue, add {@link Message}s through the {@link * enqueueMessage(Message)} method. * @@ -196,7 +196,7 @@ public void run() { // Send the message outside of the queueLock context. message.sendMessage(gatewayIP); - // Notify the listener about the repsonse. + // Notify the listener about the response. message.notifyListener(); } } catch (InterruptedException ex) { diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 0774b0a66..ab4478cef 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -176,7 +176,7 @@ private List relayCandidates() { iterator.remove(); } } - LOG.trace("Found {} addtional relay candidates: {}", relayCandidates.size(), relayCandidates); + LOG.trace("Found {} additional relay candidates: {}", relayCandidates.size(), relayCandidates); return relayCandidates; } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 5d0d3a334..854da0422 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -140,7 +140,7 @@ public void handleResponse(Message message, PeerConnection peerConnection, public void operationComplete(FutureDone future) throws Exception { if (future.isSuccess()) { Message answerMessage = future.object(); - LOG.debug("Returing from relay to requester: {}", answerMessage); + LOG.debug("Returning from relay to requester: {}", answerMessage); responder.response(answerMessage); } else { responder.failed(Type.DENIED, "Relaying message failed: " + future.failedReason()); @@ -231,8 +231,8 @@ public final Collection getPeerMap() { for (Map map : peerMap) { statistics.addAll(map.values()); } - for (PeerStatistic peerStatatistic : statistics) { - peerAddresses.add(peerStatatistic.peerAddress()); + for (PeerStatistic peerStatistic : statistics) { + peerAddresses.add(peerStatistic.peerAddress()); } return peerAddresses; } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 28473ad37..644685275 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -139,7 +139,7 @@ public FutureResponse sendPeerMap(final PeerAddress relayPeer, PeerConnection pe NeighborSet ns = new NeighborSet(255, RelayUtils.flatten(map)); message.neighborsSet(ns); - LOG.debug("send neigbors " + ns); + LOG.debug("send neighbors " + ns); // append relay-type specific data (if necessary) //relayConfig.prepareMapUpdateMessage(message); message.keepAlive(true); @@ -161,7 +161,7 @@ public void handleResponse(final Message message, PeerConnection peerConnection, // The unreachable peer receives wrapped messages from the relay handlePiggyBackedMessage(message, responder); } else if (message.type() == Type.REQUEST_3 && message.command() == RPC.Commands.RELAY.getNr()) { - // the relay server receives the update of the routing table regularly from the unrachable peer + // the relay server receives the update of the routing table regularly from the unreachable peer handleMap(message, responder); } else if (message.type() == Type.REQUEST_4 && message.command() == RPC.Commands.RELAY.getNr()) { // An unreachable peer requests the buffer at the relay peer diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index b652df54e..24f4c7826 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -67,8 +67,8 @@ public static List> unflatten(Collection flatten(List> maps) { Collection result = new ArrayList(); for (Map map : maps) { - for (PeerStatistic peerStatatistic : map.values()) { - result.add(peerStatatistic.peerAddress()); + for (PeerStatistic peerStatistic : map.values()) { + result.add(peerStatistic.peerAddress()); } } return result; @@ -207,7 +207,7 @@ public static Buffer encodeString(String content) { * Decodes buffer containing a String * * @param buffer the buffer received in a message - * @return the encodeed String + * @return the encoded String */ public static String decodeString(Buffer buffer) { if (buffer == null || buffer.buffer() == null) { @@ -263,7 +263,6 @@ public static FutureResponse send(final PeerConnection peerConnection, PeerBean * Opens a new peer connection to the receiver and sends the message through it. * @param peer * @param message - * @param config * @return */ public static FutureResponse connectAndSend(final Peer peer, final Message message) { diff --git a/replication/src/main/java/net/tomp2p/replication/Replication.java b/replication/src/main/java/net/tomp2p/replication/Replication.java index d5d28c861..38bb3910f 100644 --- a/replication/src/main/java/net/tomp2p/replication/Replication.java +++ b/replication/src/main/java/net/tomp2p/replication/Replication.java @@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory; /** - * This class has 3 methods that are called from outside eventes: check, peerInsert, peerRemoved. + * This class has 3 methods that are called from outside events: check, peerInsert, peerRemoved. */ public class Replication implements PeerMapChangeListener, ReplicationListener { private static final Logger LOG = LoggerFactory.getLogger(Replication.class); @@ -311,7 +311,7 @@ public void operationComplete(BaseFuture future) throws Exception { @Override public void exceptionCaught(Throwable t) throws Exception { - LOG.error("Unexcepted exception ocurred.", t); + LOG.error("Unexpected exception occurred.", t); } }); peer.peer().notifyAutomaticFutures(futureForkJoin); @@ -383,7 +383,7 @@ public void peerInserted(final PeerAddress peerAddress, final boolean verified) if (isInReplicationRange(myResponsibleLocation, peerAddress, replicationFactor)) { // check if I still have to replicate if (isInReplicationRange(myResponsibleLocation, selfAddress, replicationFactor)) { - LOG.debug("I {} and newly joined peer {} have replication responibility for {}.", + LOG.debug("I {} and newly joined peer {} have replication responsibility for {}.", selfAddress, peerAddress, myResponsibleLocation); // newly joined peer has to get notified FutureForkJoin> futureForkJoin = notifyMeResponsible(myResponsibleLocation, peerAddress); @@ -416,7 +416,7 @@ public void operationComplete(BaseFuture future) @Override public void exceptionCaught(Throwable t) throws Exception { - LOG.error("Unexcepted exception ocurred.", t); + LOG.error("Unexpected exception occurred.", t); } }); peer.peer().notifyAutomaticFutures(futureForkJoin); @@ -454,7 +454,7 @@ public void operationComplete(BaseFuture future) throws Exception { @Override public void exceptionCaught(Throwable t) throws Exception { - LOG.error("Unexcepted exception ocurred.", t); + LOG.error("Unexpected exception occurred.", t); } }); peer.peer().notifyAutomaticFutures(futureForkJoin); @@ -465,7 +465,7 @@ public void exceptionCaught(Throwable t) } @Override - public void peerRemoved(final PeerAddress peerAddress, final PeerStatistic peerStatatistic) { + public void peerRemoved(final PeerAddress peerAddress, final PeerStatistic peerStatistic) { if (!isReplication()) { return; } @@ -545,7 +545,7 @@ public void peerRemoved(final PeerAddress peerAddress, final PeerStatistic peerS } @Override - public void peerUpdated(final PeerAddress peerAddress, final PeerStatistic peerStatatistic) { + public void peerUpdated(final PeerAddress peerAddress, final PeerStatistic peerStatistic) { // do nothing } diff --git a/replication/src/main/java/net/tomp2p/replication/ResponsibilityListener.java b/replication/src/main/java/net/tomp2p/replication/ResponsibilityListener.java index 745599885..c072b6307 100644 --- a/replication/src/main/java/net/tomp2p/replication/ResponsibilityListener.java +++ b/replication/src/main/java/net/tomp2p/replication/ResponsibilityListener.java @@ -28,7 +28,7 @@ public interface ResponsibilityListener { /** - * The responsibilty changed to our peer. That means we are now responsible. + * The responsibility changed to our peer. That means we are now responsible. * * @param locationKey * The location key diff --git a/tracker/src/main/java/net/tomp2p/tracker/AddTrackerBuilder.java b/tracker/src/main/java/net/tomp2p/tracker/AddTrackerBuilder.java index 66bce6a08..056881cd2 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/AddTrackerBuilder.java +++ b/tracker/src/main/java/net/tomp2p/tracker/AddTrackerBuilder.java @@ -26,7 +26,7 @@ import net.tomp2p.storage.Data; public class AddTrackerBuilder extends TrackerBuilder { - private Data attachement; + private Data attachment; private SimpleBloomFilter bloomFilter; @@ -43,12 +43,12 @@ public AddTrackerBuilder(PeerTracker peer, Number160 locationKey) { self(this); } - public Data attachement() { - return attachement; + public Data attachment() { + return attachment; } - public AddTrackerBuilder attachement(Data attachement) { - this.attachement = attachement; + public AddTrackerBuilder attachment(Data attachment) { + this.attachment = attachment; return this; } @@ -107,7 +107,7 @@ public FutureTracker start() { if (peer.peer().isShutdown()) { return FUTURE_TRACKER_SHUTDOWN; } - if(attachement == null) { + if(attachment == null) { forceUDP(true); } preBuild("add-tracker-build"); @@ -120,7 +120,7 @@ public FutureTracker start() { // add myself to my local tracker, since we use a mesh we are part of // the tracker mesh as well. peer.trackerStorage().put(new Number320(locationKey, domainKey), peer.peerAddress(), keyPair() == null? null: keyPair().getPublic(), - attachement); + attachment); final FutureTracker futureTracker = peer.distributedTracker().add(this); return futureTracker; diff --git a/tracker/src/main/java/net/tomp2p/tracker/DistributedTracker.java b/tracker/src/main/java/net/tomp2p/tracker/DistributedTracker.java index 82c906dfd..45f5d6af5 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/DistributedTracker.java +++ b/tracker/src/main/java/net/tomp2p/tracker/DistributedTracker.java @@ -182,7 +182,7 @@ private void loop(Number160 locationKey, final Number160 domainKey, NavigableSet new HashSet(), new HashMap(), operation, trackerConfiguration.parallel(), new AtomicInteger(0), trackerConfiguration.maxFailure(), new AtomicInteger(0), trackerConfiguration.maxFullTrackers(), new AtomicInteger(0), - trackerConfiguration.atLeastSucessfulRequestes(), trackerConfiguration.atLeastEntriesFromTrackers(), + trackerConfiguration.atLeastSuccessfulRequests(), trackerConfiguration.atLeastEntriesFromTrackers(), new AtomicInteger(0), trackerConfiguration.maxPrimaryTrackers(), new AtomicReferenceArray(futureResponses), futureTracker, knownPeers, isGet); } @@ -192,7 +192,7 @@ private void loopRec(final Number160 locationKey, final Number160 domainKey, final Set alreadyAsked, final Set successAsked, final Map peerOnTracker, final Operation operation, final int parallel, final AtomicInteger nrFailures, final int maxFailures, final AtomicInteger trackerFull, - final int maxTrackerFull, final AtomicInteger successfulRequests, final int atLeastSuccessfullRequests, + final int maxTrackerFull, final AtomicInteger successfulRequests, final int atLeastSuccessfulRequests, final int atLeastEntriesFromTrackers, final AtomicInteger primaryTracker, final int maxPrimaryTracker, final AtomicReferenceArray futureResponses, final FutureTracker futureTracker, final Set knownPeers, final boolean isGet) { @@ -266,7 +266,7 @@ public void operationComplete(final FutureForkJoin future) throw secondaryQueue.addAll(newPeers); } int successRequests = isFull ? successfulRequests.get() : successfulRequests.incrementAndGet(); - finished = evaluate(peerOnTracker, successRequests, atLeastSuccessfullRequests, + finished = evaluate(peerOnTracker, successRequests, atLeastSuccessfulRequests, atLeastEntriesFromTrackers, isGet); LOG.debug("evaluation result: finished={}, {} / {}", finished, peerOnTracker.size(), @@ -285,13 +285,13 @@ public void operationComplete(final FutureForkJoin future) throw LOG.debug("no success {}", future.failedReason()); finished = nrFailures.incrementAndGet() > maxFailures; } - // check if done, or continune looping + // check if done, or continue looping if (finished) { Set potentialTrackers = new HashSet(queueToAsk); potentialTrackers.addAll(secondaryQueue); LOG.debug("we finished2, we asked {}, but we could ask {} more nodes ({} / {})", - alreadyAsked.size(), queueToAsk.size(), successfulRequests, atLeastSuccessfullRequests); + alreadyAsked.size(), queueToAsk.size(), successfulRequests, atLeastSuccessfulRequests); futureTracker.trackers(potentialTrackers, successAsked, peerOnTracker, future.futuresCompleted()); if (cancelOnFinish) { @@ -300,7 +300,7 @@ public void operationComplete(final FutureForkJoin future) throw } else { loopRec(locationKey, domainKey, queueToAsk, secondaryQueue, alreadyAsked, successAsked, peerOnTracker, operation, parallel, nrFailures, maxFailures, trackerFull, maxTrackerFull, - successfulRequests, atLeastSuccessfullRequests, atLeastEntriesFromTrackers, primaryTracker, + successfulRequests, atLeastSuccessfulRequests, atLeastEntriesFromTrackers, primaryTracker, maxPrimaryTracker, futureResponses, futureTracker, knownPeers, isGet); } } @@ -420,7 +420,7 @@ public interface Operation { * @param primary * If the remote peer is a primary tracker, the flag is set * to true - * @return The future reponse of the RPC + * @return The future response of the RPC */ FutureResponse create(PeerAddress address, boolean primary); } diff --git a/tracker/src/main/java/net/tomp2p/tracker/FutureTracker.java b/tracker/src/main/java/net/tomp2p/tracker/FutureTracker.java index f405528ac..79396bfca 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/FutureTracker.java +++ b/tracker/src/main/java/net/tomp2p/tracker/FutureTracker.java @@ -94,7 +94,7 @@ public void trackers(Set potentialTrackers, Set direct this.type = ((potentialTrackers.size() == 0) && (directTrackers.size() == 0)) ? BaseFuture.FutureType.FAILED : BaseFuture.FutureType.OK; if (this.type == BaseFuture.FutureType.FAILED) { - this.reason = "we did not find anything, are you sure you are serching for the right tracker?"; + this.reason = "we did not find anything, are you sure you are searching for the right tracker?"; } } notifyListeners(); diff --git a/tracker/src/main/java/net/tomp2p/tracker/GetTrackerBuilder.java b/tracker/src/main/java/net/tomp2p/tracker/GetTrackerBuilder.java index 657e27a6c..853a0f703 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/GetTrackerBuilder.java +++ b/tracker/src/main/java/net/tomp2p/tracker/GetTrackerBuilder.java @@ -25,24 +25,24 @@ public class GetTrackerBuilder extends TrackerBuilder { private Set knownPeers; - private boolean expectAttachement = false; + private boolean expectAttachment = false; public GetTrackerBuilder(PeerTracker peer, Number160 locationKey) { super(peer, locationKey); self(this); } - public boolean isExpectAttachement() { - return expectAttachement; + public boolean isExpectAttachment() { + return expectAttachment; } - public GetTrackerBuilder expectAttachement() { - this.expectAttachement = true; + public GetTrackerBuilder expectAttachment() { + this.expectAttachment = true; return this; } - public GetTrackerBuilder expectAttachement(boolean expectAttachement) { - this.expectAttachement = expectAttachement; + public GetTrackerBuilder expectAttachment(boolean expectAttachment) { + this.expectAttachment = expectAttachment; return this; } @@ -51,7 +51,7 @@ public FutureTracker start() { return FUTURE_TRACKER_SHUTDOWN; } - if(!expectAttachement) { + if(!expectAttachment) { forceUDP(true); } diff --git a/tracker/src/main/java/net/tomp2p/tracker/PeerBuilderTracker.java b/tracker/src/main/java/net/tomp2p/tracker/PeerBuilderTracker.java index a28c22cd0..1763746ee 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/PeerBuilderTracker.java +++ b/tracker/src/main/java/net/tomp2p/tracker/PeerBuilderTracker.java @@ -195,13 +195,13 @@ public TrackerTriple get() { } TrackerData trackerData = new TrackerData(value); - Map peerStatatisticsMap = trackerData.peerAddresses(); + Map peerStatisticsMap = trackerData.peerAddresses(); - if(peerStatatisticsMap == null || peerStatatisticsMap.size() == 0) { + if(peerStatisticsMap == null || peerStatisticsMap.size() == 0) { return null; } - Collection peerStatatistics = peerStatatisticsMap.keySet(); + Collection peerStatatistics = peerStatisticsMap.keySet(); if (peerStatatistics.isEmpty()) { return null; } diff --git a/tracker/src/main/java/net/tomp2p/tracker/TrackerConfiguration.java b/tracker/src/main/java/net/tomp2p/tracker/TrackerConfiguration.java index 7d7f02d41..88d58c1bb 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/TrackerConfiguration.java +++ b/tracker/src/main/java/net/tomp2p/tracker/TrackerConfiguration.java @@ -70,7 +70,7 @@ public int parallel() { return parallel; } - public int atLeastSucessfulRequestes() { + public int atLeastSuccessfulRequests() { return atLeastSuccessfulRequests; } diff --git a/tracker/src/main/java/net/tomp2p/tracker/TrackerRPC.java b/tracker/src/main/java/net/tomp2p/tracker/TrackerRPC.java index 772408dcb..92fdcccf5 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/TrackerRPC.java +++ b/tracker/src/main/java/net/tomp2p/tracker/TrackerRPC.java @@ -86,12 +86,12 @@ public FutureResponse addToTracker(final PeerAddress remotePeer, AddTrackerBuild if (peerAddressToAnnounce == null) { peerAddressToAnnounce = peerBean().serverPeerAddress(); } - trackerData.put(peerAddressToAnnounce, builder.attachement()); + trackerData.put(peerAddressToAnnounce, builder.attachment()); trackerData = UtilsTracker.limit(trackerData, TrackerRPC.MAX_MSG_SIZE_UDP); message.trackerData(trackerData); LOG.debug("tracker PUT {}", message); - if (builder.isForceTCP() || builder.attachement()!=null) { + if (builder.isForceTCP() || builder.attachment()!=null) { return requestHandler.sendTCP(channelCreator); } else { return requestHandler.sendUDP(channelCreator); @@ -121,7 +121,7 @@ public FutureResponse getFromTracker(final PeerAddress remotePeer, GetTrackerBui connectionBean(), builder); LOG.debug("tracker GET {}", message); - if ((builder.isExpectAttachement() || builder.isForceTCP())) { + if ((builder.isExpectAttachment() || builder.isForceTCP())) { return requestHandler.sendTCP(channelCreator); } else { return requestHandler.sendUDP(channelCreator); diff --git a/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java b/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java index c81a8d442..30d1cc58e 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java +++ b/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java @@ -42,7 +42,7 @@ public class TrackerStorage implements Maintainable, PeerMapChangeListener, Peer final private boolean verifyPeersOnTracker; private final int[] intervalSeconds; private final PeerAddress self; - private final int trackerTimoutSeconds; + private final int trackerTimeoutSeconds; private final PeerMap peerMap; private final int replicationFactor; //comes later @@ -54,7 +54,7 @@ public TrackerStorage(int trackerTimoutSeconds, final int[] intervalSeconds, true); dataMap = new ConcurrentCacheMap>>(trackerTimoutSeconds, TRACKER_CACHE_SIZE, true); peerOffline = new ConcurrentCacheMap(trackerTimoutSeconds * 5, TRACKER_CACHE_SIZE, false); - this.trackerTimoutSeconds = trackerTimoutSeconds; + this.trackerTimeoutSeconds = trackerTimoutSeconds; this.intervalSeconds = intervalSeconds; this.self = self; this.peerMap = peerMap; @@ -62,7 +62,7 @@ public TrackerStorage(int trackerTimoutSeconds, final int[] intervalSeconds, this.verifyPeersOnTracker = verifyPeersOnTracker; } - public boolean put(Number320 key, PeerAddress peerAddress, PublicKey publicKey, Data attachement) { + public boolean put(Number320 key, PeerAddress peerAddress, PublicKey publicKey, Data attachment) { if (peerOffline.containsKey(peerAddress.peerId())) { return false; } @@ -90,11 +90,11 @@ public boolean put(Number320 key, PeerAddress peerAddress, PublicKey publicKey, } } - if(attachement == null) { - attachement = new Data(); + if(attachment == null) { + attachment = new Data(); } // now store - attachement.publicKey(publicKey); + attachment.publicKey(publicKey); final Map>> dataMapToStore; if(isUnverified) { dataMapToStore = dataMapUnverified; @@ -105,7 +105,7 @@ public boolean put(Number320 key, PeerAddress peerAddress, PublicKey publicKey, } else { dataMapToStore = dataMap; } - return add(key, peerAddress, dataMapToStore, attachement); + return add(key, peerAddress, dataMapToStore, attachment); } private Pair findOld(Number320 key, PeerAddress peerAddress, Map>> dataMap) { @@ -192,7 +192,7 @@ private boolean isInReplicationRange(final Number160 locationKey, final PeerAddr return tmp.headSet(new PeerStatistic(peerAddress)).size() < replicationFactor; } - private boolean add(Number320 key, PeerAddress peerAddress, Map>> map, Data attachement) { + private boolean add(Number320 key, PeerAddress peerAddress, Map>> map, Data attachment) { //check size Map> map2 = map.get(key); @@ -202,11 +202,11 @@ private boolean add(Number320 key, PeerAddress peerAddress, Map trackerData = findOld(key, peerAddress, map); if (trackerData == null) { - trackerData = new Pair(new PeerStatistic(peerAddress), attachement); + trackerData = new Pair(new PeerStatistic(peerAddress), attachment); } if(map2 == null) { - map2 = new ConcurrentCacheMap>(trackerTimoutSeconds, TRACKER_CACHE_SIZE, true); + map2 = new ConcurrentCacheMap>(trackerTimeoutSeconds, TRACKER_CACHE_SIZE, true); map.put(key, map2); } map2.put(peerAddress, trackerData); @@ -232,7 +232,7 @@ private Map>> removeFromMa for (Map.Entry>> entry : map.entrySet()) { Pair oldPair = entry.getValue().remove(remotePeer); if(oldPair != null) { - Map> map2 = new ConcurrentCacheMap>(trackerTimoutSeconds, TRACKER_CACHE_SIZE, true); + Map> map2 = new ConcurrentCacheMap>(trackerTimeoutSeconds, TRACKER_CACHE_SIZE, true); map2.put(remotePeer, oldPair); removed.put(entry.getKey(), map2); } diff --git a/tracker/src/main/java/net/tomp2p/tracker/UtilsTracker.java b/tracker/src/main/java/net/tomp2p/tracker/UtilsTracker.java index d22834c85..c90dc4af5 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/UtilsTracker.java +++ b/tracker/src/main/java/net/tomp2p/tracker/UtilsTracker.java @@ -48,7 +48,7 @@ public static TrackerData disjunction(TrackerData meshPeers, SimpleBloomFilter Date: Thu, 8 Oct 2015 17:09:49 +0200 Subject: [PATCH 091/135] fixed typos --- .../src/test/java/net/tomp2p/tracker/TestTracker.java | 10 +++++----- .../test/java/net/tomp2p/tracker/TestTrackerRPC.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java index ab14b55b1..21e10d6dc 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java @@ -301,25 +301,25 @@ public void testTracker5() throws Exception { Number160 trackerID = new Number160(rnd); FutureTracker ft = nodes[300].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[301].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[302].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[303].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); Assert.assertEquals(true, ft.isSuccess()); Assert.assertEquals(2, ft.directTrackers().size()); tc = new TrackerConfiguration(1, 1, 0, 1); ft = nodes[199].getTracker(trackerID).domainKey(Number160.createHash("test")) - .routingConfiguration(rc).trackerConfiguration(tc).expectAttachement() + .routingConfiguration(rc).trackerConfiguration(tc).expectAttachment() .start(); ft.awaitUninterruptibly(); Assert.assertEquals(true, ft.isSuccess()); diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java index 363406635..2459ba0dd 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java @@ -147,7 +147,7 @@ public void testTrackerPutAttachment() throws Exception { AddTrackerBuilder addTrackerBuilder = new AddTrackerBuilder(sender, loc); addTrackerBuilder.domainKey(dom); - addTrackerBuilder.attachement(new Data("data")); + addTrackerBuilder.attachment(new Data("data")); FutureResponse fr = sender.trackerRPC().addToTracker(recv1.peerAddress(), addTrackerBuilder, cc); @@ -158,7 +158,7 @@ public void testTrackerPutAttachment() throws Exception { GetTrackerBuilder getTrackerBuilder = new GetTrackerBuilder(sender, loc); getTrackerBuilder.domainKey(dom); - getTrackerBuilder.expectAttachement(true); + getTrackerBuilder.expectAttachment(true); fr = sender.trackerRPC().getFromTracker(recv1.peerAddress(), getTrackerBuilder, cc); fr.awaitUninterruptibly(); @@ -202,7 +202,7 @@ public void testTrackerBloomFilter() throws Exception { AddTrackerBuilder addTrackerBuilder = new AddTrackerBuilder(sender, loc); addTrackerBuilder.domainKey(dom); - addTrackerBuilder.attachement(new Data("data")); + addTrackerBuilder.attachment(new Data("data")); addTrackerBuilder.setBloomFilter(bloomFilter); FutureResponse fr = sender.trackerRPC().addToTracker(recv1.peerAddress(), @@ -214,7 +214,7 @@ public void testTrackerBloomFilter() throws Exception { bloomFilter.add(sender.peerAddress().peerId()); GetTrackerBuilder getTrackerBuilder = new GetTrackerBuilder(sender, loc); - getTrackerBuilder.expectAttachement(true); + getTrackerBuilder.expectAttachment(true); getTrackerBuilder.knownPeers(bloomFilter); getTrackerBuilder.domainKey(dom); From f75a7c6199416796ee079ad8565c5c0071cb4589 Mon Sep 17 00:00:00 2001 From: Esfomeado Date: Thu, 8 Oct 2015 16:13:02 +0100 Subject: [PATCH 092/135] Ups forgot this! --- .../src/test/java/net/tomp2p/tracker/TestTracker.java | 10 +++++----- .../test/java/net/tomp2p/tracker/TestTrackerRPC.java | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java index ab14b55b1..21e10d6dc 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java @@ -301,25 +301,25 @@ public void testTracker5() throws Exception { Number160 trackerID = new Number160(rnd); FutureTracker ft = nodes[300].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[301].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[302].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); ft = nodes[303].addTracker(trackerID).domainKey(Number160.createHash("test")) .routingConfiguration(rc).trackerConfiguration(tc) - .attachement(new Data(",.peoueuaoeue")).start(); + .attachment(new Data(",.peoueuaoeue")).start(); ft.awaitUninterruptibly(); Assert.assertEquals(true, ft.isSuccess()); Assert.assertEquals(2, ft.directTrackers().size()); tc = new TrackerConfiguration(1, 1, 0, 1); ft = nodes[199].getTracker(trackerID).domainKey(Number160.createHash("test")) - .routingConfiguration(rc).trackerConfiguration(tc).expectAttachement() + .routingConfiguration(rc).trackerConfiguration(tc).expectAttachment() .start(); ft.awaitUninterruptibly(); Assert.assertEquals(true, ft.isSuccess()); diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java index 363406635..2459ba0dd 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerRPC.java @@ -147,7 +147,7 @@ public void testTrackerPutAttachment() throws Exception { AddTrackerBuilder addTrackerBuilder = new AddTrackerBuilder(sender, loc); addTrackerBuilder.domainKey(dom); - addTrackerBuilder.attachement(new Data("data")); + addTrackerBuilder.attachment(new Data("data")); FutureResponse fr = sender.trackerRPC().addToTracker(recv1.peerAddress(), addTrackerBuilder, cc); @@ -158,7 +158,7 @@ public void testTrackerPutAttachment() throws Exception { GetTrackerBuilder getTrackerBuilder = new GetTrackerBuilder(sender, loc); getTrackerBuilder.domainKey(dom); - getTrackerBuilder.expectAttachement(true); + getTrackerBuilder.expectAttachment(true); fr = sender.trackerRPC().getFromTracker(recv1.peerAddress(), getTrackerBuilder, cc); fr.awaitUninterruptibly(); @@ -202,7 +202,7 @@ public void testTrackerBloomFilter() throws Exception { AddTrackerBuilder addTrackerBuilder = new AddTrackerBuilder(sender, loc); addTrackerBuilder.domainKey(dom); - addTrackerBuilder.attachement(new Data("data")); + addTrackerBuilder.attachment(new Data("data")); addTrackerBuilder.setBloomFilter(bloomFilter); FutureResponse fr = sender.trackerRPC().addToTracker(recv1.peerAddress(), @@ -214,7 +214,7 @@ public void testTrackerBloomFilter() throws Exception { bloomFilter.add(sender.peerAddress().peerId()); GetTrackerBuilder getTrackerBuilder = new GetTrackerBuilder(sender, loc); - getTrackerBuilder.expectAttachement(true); + getTrackerBuilder.expectAttachment(true); getTrackerBuilder.knownPeers(bloomFilter); getTrackerBuilder.domainKey(dom); From 94dbf4e5a65b94c9aa3aa3c339f86dca928d1441 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 16:00:33 +0200 Subject: [PATCH 093/135] fixing RCON --- .../net/tomp2p/connection/Dispatcher.java | 11 ++++---- .../java/net/tomp2p/connection/Sender.java | 1 + .../net/tomp2p/relay/DistributedRelay.java | 11 ++++---- .../main/java/net/tomp2p/relay/Forwarder.java | 25 ++++++++++++++++--- .../main/java/net/tomp2p/relay/RconRPC.java | 8 +++--- .../test/java/net/tomp2p/relay/TestRcon.java | 3 ++- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index b237ff8ab..4a82f7521 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -243,27 +243,28 @@ private void printWarnMessage(Message message) { private class DirectResponder implements Responder { final ChannelHandlerContext ctx; final Message requestMessage; + DirectResponder(final ChannelHandlerContext ctx, final Message requestMessage) { this.ctx = ctx; this.requestMessage = requestMessage; } @Override - public FutureDone response(Message responseMessage) { - return Dispatcher.this.response(ctx, responseMessage); + public FutureDone response(final Message responseMessage) { + return Dispatcher.this.response(ctx, responseMessage); } @Override public void failed(Message.Type type, String reason) { - Message responseMessage = DispatchHandler.createResponseMessage(requestMessage, type, peerBeanMaster.serverPeerAddress()); + final Message responseMessage = DispatchHandler.createResponseMessage(requestMessage, type, peerBeanMaster.serverPeerAddress()); Dispatcher.this.response(ctx, responseMessage); } @Override public void responseFireAndForget() { - LOG.debug("The reply handler was a fire-and-forget handler. No message is sent back for {}.", requestMessage); + LOG.debug("The reply handler was a fire-and-forget handler. No message is sent back for {}.", requestMessage); if (!(ctx.channel() instanceof DatagramChannel)) { - String msg = "There is no TCP fire-and-forget. Use UDP in that case. "; + final String msg = "There is no TCP fire-and-forget. Use UDP in that case. "; LOG.warn(msg + requestMessage); throw new RuntimeException(msg); } else { diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 27691542e..8f8748d28 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -758,6 +758,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { afterSend(writeFuture, futureResponse, fireAndForget); } else { LOG.warn("Channel creation failed", future.cause()); + LOG.warn("Faild message {}", message); futureResponse.failed("Channel creation failed " + future.channel() + "/" + future.cause()); // may have been closed by the other side, // or it may have been canceled from this side diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index ab4478cef..8ac5263e7 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -129,7 +129,7 @@ public FutureDone shutdown() { * @return RelayFuture containing a {@link DistributedRelay} instance */ public DistributedRelay setupRelays(List relays) { - this.relays = relays; + this.relays = Collections.synchronizedList(relays); executorService.submit(new Runnable() { @Override public void run() { @@ -150,15 +150,12 @@ private List relayCandidates() { // candidates are neighboring peers that are not relayed themselves and have // not recently failed as relay or denied acting as relay. relayCandidates = peer.distributedRouting().peerMap().all(); - // remove those who we know have failed - relayCandidates.removeAll(failedRelays); } else { - // if the user sets manual relays, the failed relays are not removed, as this has to be done by - // the user synchronized (relays) { relayCandidates = new ArrayList(relays); } } + relayCandidates.removeAll(failedRelays); //filterRelayCandidates for (Iterator iterator = relayCandidates.iterator(); iterator.hasNext();) { @@ -176,7 +173,7 @@ private List relayCandidates() { iterator.remove(); } } - LOG.trace("Found {} additional relay candidates: {}", relayCandidates.size(), relayCandidates); + LOG.trace("Found {} additional relay candidates: {}, failed are {}", relayCandidates.size(), relayCandidates, failedRelays); return relayCandidates; } @@ -284,9 +281,11 @@ public void operationComplete(final FutureDone futureClose) }); } else { LOG.debug("bad relay: {}", candidate); + failedRelays.add(candidate); activeClients.remove(candidate); updatePeerAddress(); relayCallback.onRelayRemoved(candidate, future.object()); + } //loop again startConnectionsLoop(); diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 854da0422..70ecde8c2 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -133,17 +133,17 @@ public void handleResponse(Message message, PeerConnection peerConnection, handleNeigbhor(message, responder); } else { messageCounter.incrementAndGet(); - LOG.debug("Received message {} to forward to unreachable peer {}", message, unreachablePeerConnection.remotePeer()); + LOG.debug("Received message {} to forward to unreachable peer 1 {}", message, unreachablePeerConnection.remotePeer()); FutureDone response = forwardOrBuffer(message); response.addListener(new BaseFutureAdapter>() { @Override public void operationComplete(FutureDone future) throws Exception { if (future.isSuccess()) { Message answerMessage = future.object(); - LOG.debug("Returning from relay to requester: {}", answerMessage); + LOG.debug("Returning from relay to requester: 1 {}", answerMessage); responder.response(answerMessage); } else { - responder.failed(Type.DENIED, "Relaying message failed: " + future.failedReason()); + responder.failed(Type.DENIED, "Relaying message failed: 1 " + future.failedReason()); } } }); @@ -151,6 +151,25 @@ public void operationComplete(FutureDone future) throws Exception { } + public void handleForward(final Message forwardMessage, final Message message, final Responder responder) { + messageCounter.incrementAndGet(); + LOG.debug("Received message {} to forward to unreachable peer {}, orig: {}", forwardMessage, unreachablePeerConnection.remotePeer(), message); + final FutureDone response = forwardOrBuffer(forwardMessage); + response.addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(FutureDone future) throws Exception { + if (future.isSuccess()) { + final Message answerMessage = createResponseMessage(message, Type.OK); + LOG.debug("Returning from relay to requester: 2 {}", answerMessage); + responder.response(answerMessage); + } else { + responder.failed(Type.DENIED, "Relaying message failed: 2 " + future.failedReason()); + } + } + }); + + } + /** * When a ping message is received * diff --git a/nat/src/main/java/net/tomp2p/relay/RconRPC.java b/nat/src/main/java/net/tomp2p/relay/RconRPC.java index 515512c20..17444462c 100644 --- a/nat/src/main/java/net/tomp2p/relay/RconRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RconRPC.java @@ -67,15 +67,15 @@ public void handleResponse(final Message message, final PeerConnection peerConne LOG.debug("received RconRPC message {}", message); if (message.type() == Message.Type.REQUEST_1 && message.command() == RPC.Commands.RCON.getNr()) { // the message reached the relay peer - LOG.debug("handle RconForward for message: " + message); + LOG.debug("handle RconForward for message: {}", message); handleRconForward(message, responder); } else if (message.type() == Message.Type.REQUEST_2 && message.command() == RPC.Commands.RCON.getNr()) { // the message reached the unreachable peer - LOG.debug("handle RconSetup for message: " + message); + LOG.debug("handle RconSetup for message: {}", message); handleRconSetup(message, responder); } else if (message.type() == Message.Type.REQUEST_3 && message.command() == RPC.Commands.RCON.getNr()) { // the message reached the requesting peer - LOG.debug("handle RconAfterconnect for message: " + message); + LOG.debug("handle RconAfterconnect for message: {}", message); handleRconAfterconnect(message, responder, peerConnection); } else { LOG.warn("received invalid RconRPC message {}", message); @@ -98,7 +98,7 @@ private void handleRconForward(final Message message, final Responder responder) final Forwarder forwarder = extractRelayForwarder(message); if (forwarder != null) { final Message forwardMessage = createForwardMessage(message, forwarder.unreachablePeerAddress()); - forwarder.handleResponse(forwardMessage, null, true, responder); + forwarder.handleForward(forwardMessage, message, responder); } else { handleFail(message, responder, "No RelayForwarder registered for peerId=" + message.recipient().peerId().toString()); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRcon.java b/nat/src/test/java/net/tomp2p/relay/TestRcon.java index d8e6c7503..a74812ea8 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRcon.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRcon.java @@ -134,6 +134,7 @@ public void testReverseConnection() throws Exception { System.err.println("testReverseConnection() start!"); final String requestString = "This is a test String"; + final String replyString = "SUCCESS HIT"; final CountDownLatch cLatch = new CountDownLatch(1); unreachable.objectDataReply(new ObjectDataReply() { @@ -144,7 +145,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { System.err.println("received: " + (String) request); cLatch.countDown(); } - return null; + return replyString; } }); From 176084e15e6580e26ef2628997f4f52f1f6bdc85 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 16:52:32 +0200 Subject: [PATCH 094/135] update travis --- .travis.yml | 11 ++++ .../main/java/net/tomp2p/relay/Forwarder.java | 10 +++- .../main/java/net/tomp2p/relay/RelayType.java | 54 ------------------- 3 files changed, 19 insertions(+), 56 deletions(-) delete mode 100644 nat/src/main/java/net/tomp2p/relay/RelayType.java diff --git a/.travis.yml b/.travis.yml index ca3783a72..4807d5b3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,14 @@ jdk: #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" #script: mvn -Dtest=net.tomp2p.p2p.TestAnnounce test && exit 1 + +install: mvn install -DskipTests=true + +before_script: + - sudo sh -c 'echo "$USER ALL=(ALL) NOPASSWD: ${pwd}/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "$USER ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' + - sudo cat /etc/sudoers + - chmod a+x {pwd}/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh + - ls -la + +script: mvn test -Dmaven.javadoc.skip=true diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 70ecde8c2..99fb11814 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -44,7 +44,7 @@ public class Forwarder extends DispatchHandler { private final List buffer = Collections.synchronizedList(new ArrayList()); - //private int capacity = 16; + private int capacity = 16; private long lastAccess = System.currentTimeMillis(); private int bufferTimeSec = 60; @@ -266,12 +266,18 @@ public final Collection getPeerMap() { public final void setPeerMap(List> peerMap, Message requestMessage, Message preparedResponse) { this.peerMap = peerMap; + checkSend(); } private void addToBuffer(Message requestMessage) { buffer.add(requestMessage); - if(buffer.size() > 16 || lastAccess + (bufferTimeSec * 1000) < System.currentTimeMillis()) { + checkSend(); + } + + private void checkSend() { + if(buffer.size() > capacity || lastAccess + (bufferTimeSec * 1000) < System.currentTimeMillis()) { forwardMessages(buffer); + lastAccess = System.currentTimeMillis(); } } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayType.java b/nat/src/main/java/net/tomp2p/relay/RelayType.java deleted file mode 100644 index 676c38c5c..000000000 --- a/nat/src/main/java/net/tomp2p/relay/RelayType.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.tomp2p.relay; - -public enum RelayType { - - /** - * Data exchange will happen over an open TCP connection - */ - OPENTCP(true, 5, false), - - /** - * Data exchange will take place over Google Cloud Messaging. The server buffers multiple requests. - */ - ANDROID(false, 4, true), - - /** - * Same as {@link #OPENTCP}, but the server buffers messages and sends them in bulk. - */ - BUFFERED_OPENTCP(true, 5, true); - - private final boolean keepConnectionOpen; - private final int maxRelayCount; - private final boolean isSlow; - - private RelayType(boolean keepConnectionOpen, int maxRelayCount, boolean isSlow) { - this.keepConnectionOpen = keepConnectionOpen; - this.maxRelayCount = maxRelayCount; - this.isSlow = isSlow; - } - - /** - * Returns whether a peer connection should be kept open or not. - * - * @return - */ - public boolean keepConnectionOpen() { - return keepConnectionOpen; - } - - /** - * Returns the maximum allowed number of relays. - */ - public int maxRelayCount() { - return maxRelayCount; - } - - /** - * Returns whether this type is 'slow' or not. - * - * @return - */ - public boolean isSlow() { - return isSlow; - } -} From 68485153eeceae773ec3bb229f219b8738ff6a8d Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:00:50 +0200 Subject: [PATCH 095/135] travis -> sudoers --- .travis.yml | 10 ++-- .../java/net/tomp2p/relay/FutureRelay.jav | 52 ------------------- 2 files changed, 5 insertions(+), 57 deletions(-) delete mode 100644 nat/src/main/java/net/tomp2p/relay/FutureRelay.jav diff --git a/.travis.yml b/.travis.yml index 4807d5b3c..fe8f08918 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,13 +7,13 @@ jdk: #script: mvn -Dtest=net.tomp2p.p2p.TestAnnounce test && exit 1 -install: mvn install -DskipTests=true +install: mvn install -DskipTests=true -B before_script: - - sudo sh -c 'echo "$USER ALL=(ALL) NOPASSWD: ${pwd}/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh" >> /etc/sudoers' - - sudo sh -c 'echo "$USER ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' - - sudo cat /etc/sudoers - - chmod a+x {pwd}/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh + - chmod a+x /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh - ls -la + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' + - sudo cat /etc/sudoers script: mvn test -Dmaven.javadoc.skip=true diff --git a/nat/src/main/java/net/tomp2p/relay/FutureRelay.jav b/nat/src/main/java/net/tomp2p/relay/FutureRelay.jav deleted file mode 100644 index fd65e5298..000000000 --- a/nat/src/main/java/net/tomp2p/relay/FutureRelay.jav +++ /dev/null @@ -1,52 +0,0 @@ -package net.tomp2p.relay; - -import java.util.Collection; - -import net.tomp2p.futures.BaseFutureImpl; - -public class FutureRelay extends BaseFutureImpl { - - private Collection relays; - - private boolean isRelayNotRequired; - - public FutureRelay() { - self(this); - } - - public FutureRelay nothingTodo() { - synchronized (lock) { - if (!completedAndNotify()) { - return this; - } - type = FutureType.OK; - isRelayNotRequired = true; - } - notifyListeners(); - return this; - } - - public FutureRelay done(Collection relays) { - synchronized (lock) { - if (!completedAndNotify()) { - return this; - } - type = FutureType.OK; - this.relays = relays; - } - notifyListeners(); - return this; - } - - public boolean isRelayNotRequired() { - synchronized (lock) { - return isRelayNotRequired; - } - } - - public Collection relays() { - synchronized (lock) { - return relays; - } - } -} From 0964a28e91ecd6ea376e6ffd30e2e22390b08997 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:04:41 +0200 Subject: [PATCH 096/135] travis -> sudoer --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fe8f08918..c7c9e0757 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ jdk: install: mvn install -DskipTests=true -B before_script: - - chmod a+x /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh + - chmod a+x /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh - ls -la - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh" >> /etc/sudoers' - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' - sudo cat /etc/sudoers From 6f19ef1fb58d0aa2549e510501e23076e5aa97e7 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:10:31 +0200 Subject: [PATCH 097/135] travis -> sudoers --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7c9e0757..6ad611c80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ jdk: install: mvn install -DskipTests=true -B before_script: - - chmod a+x /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh + - chmod a+x /home/travis/build/tomp2p/TomP2P/tomp2p-nat/src/test/resources/nat-net.sh - ls -la - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p-nat/src/test/resources/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p/TomP2P/tomp2p-nat/src/test/resources/nat-net.sh" >> /etc/sudoers' - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' - sudo cat /etc/sudoers From 16a9d74c6dbc09918946829f123d411566108dfe Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:16:46 +0200 Subject: [PATCH 098/135] travit -> sudoers --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6ad611c80..f4cfaa050 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,9 @@ jdk: install: mvn install -DskipTests=true -B before_script: - - chmod a+x /home/travis/build/tomp2p/TomP2P/tomp2p-nat/src/test/resources/nat-net.sh + - chmod a+x /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh - ls -la - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p/TomP2P/tomp2p-nat/src/test/resources/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh" >> /etc/sudoers' - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' - sudo cat /etc/sudoers From 7dd48f5142f1e2b182a57109ed7341658c919313 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:27:58 +0200 Subject: [PATCH 099/135] travis -> sudoers --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f4cfaa050..52b89b21d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ install: mvn install -DskipTests=true -B before_script: - chmod a+x /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh - ls -la - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh" >> /etc/sudoers' - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD: /sbin/ip" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh" >> /etc/sudoers' + - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /usr/bin/ip" >> /etc/sudoers' - sudo cat /etc/sudoers script: mvn test -Dmaven.javadoc.skip=true From c835c152872ebca04cc94dcf456fd1b6b4ef7c66 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 17:53:22 +0200 Subject: [PATCH 100/135] disabling NAT tests --- .travis.yml | 16 ++++++---------- .../java/net/tomp2p/connection/Dispatcher.java | 12 ++++++++++++ .../main/java/net/tomp2p/relay/RelayRPC.java | 15 +-------------- .../main/java/net/tomp2p/relay/RelayUtils.java | 10 ++++------ .../tomp2p/holep/manual/TestNATForwarding.java | 8 +++++--- .../net/tomp2p/holep/manual/TestNATLocal.java | 5 ++++- .../net/tomp2p/holep/manual/TestNATRelay.java | 7 +++++-- .../net/tomp2p/holep/manual/TestNATStress.java | 7 ++++++- .../holep/manual/TestNATTypeDetection.java | 17 ++++++++++------- .../java/net/tomp2p/holep/manual/TestUPNP.java | 5 +++++ 10 files changed, 58 insertions(+), 44 deletions(-) diff --git a/.travis.yml b/.travis.yml index 52b89b21d..8e6a407a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,17 +3,13 @@ language: java jdk: - openjdk7 +#solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" -#script: mvn -Dtest=net.tomp2p.p2p.TestAnnounce test && exit 1 +#does not work as reported here: https://github.com/travis-ci/travis-ci/issues/1341 +#before_script: +# - chmod a+x /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh +# - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh" >> /etc/sudoers' +# - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /usr/bin/ip" >> /etc/sudoers' -install: mvn install -DskipTests=true -B -before_script: - - chmod a+x /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh - - ls -la - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /home/travis/build/tomp2p/TomP2P/nat/src/test/resources/nat-net.sh" >> /etc/sudoers' - - sudo sh -c 'echo "travis ALL=(ALL) NOPASSWD":" /usr/bin/ip" >> /etc/sudoers' - - sudo cat /etc/sudoers - -script: mvn test -Dmaven.javadoc.skip=true diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 4a82f7521..a412afcaf 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -181,6 +181,18 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa return; } + + //handle late responses from pending requests + final FutureResponse lateRequests = getPendingRequests().get(message.messageId()); + if(lateRequests!=null) { + lateRequests.response(message); + Message responseMessage = DispatchHandler.createResponseMessage(message, Type.OK, peerBeanMaster.serverPeerAddress()); + response(ctx, responseMessage); + } else { + Message responseMessage = DispatchHandler.createResponseMessage(message, Type.NOT_FOUND, peerBeanMaster.serverPeerAddress()); + response(ctx, responseMessage); + } + if (!message.isRequest()) { LOG.debug("Handing request message to the next handler. {}", message); ctx.fireChannelRead(message); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 644685275..e8eb62df1 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -167,9 +167,6 @@ public void handleResponse(final Message message, PeerConnection peerConnection, // An unreachable peer requests the buffer at the relay peer // or a buffer is transmitted to the unreachable peer directly handleBuffer(message, responder); - } else if (message.type() == Type.REQUEST_5 && message.command() == RPC.Commands.RELAY.getNr()) { - // A late response - handleLateResponse(message, peerConnection, sign, responder); } else { throw new IllegalArgumentException("Message content is wrong"); } @@ -383,6 +380,7 @@ public FutureDone response(Message responseMessage) { } responseMessage.recipient(responseMessage.recipient().changeAddress(sender.getAddress()).changePorts(sender.getPort(), sender.getPort())); + FutureResponse fr = RelayUtils.connectAndSend(peer(), responseMessage); final FutureDone fd = new FutureDone(); fr.addListener(new BaseFutureAdapter() { @@ -405,15 +403,4 @@ public void failed(Type type, String reason) { responder.response(createResponseMessage(message, Type.OK)); } - private void handleLateResponse(Message message, - PeerConnection peerConnection, boolean sign, Responder responder) { - FutureResponse fr = connectionBean().dispatcher().getPendingRequests().get(message.messageId()); - if(fr!=null) { - fr.response(message); - responder.response(createResponseMessage(message, Type.OK)); - } else { - responder.response(createResponseMessage(message, Type.NOT_FOUND)); - } - - } } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 24f4c7826..80913b69d 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -267,15 +267,13 @@ public static FutureResponse send(final PeerConnection peerConnection, PeerBean */ public static FutureResponse connectAndSend(final Peer peer, final Message message) { final FutureResponse futureResponse = new FutureResponse(message); - final FuturePeerConnection fpc = peer.createPeerConnection(message.recipient()); + final RequestHandler requestHandler = new RequestHandler(futureResponse, peer.peerBean(), peer.connectionBean(), peer.connectionBean().channelServer().channelServerConfiguration()); + final FutureChannelCreator fpc = peer.connectionBean().reservation().create(0, 1); + fpc.addListener(new BaseFutureAdapter() { public void operationComplete(final FuturePeerConnection futurePeerConnection) throws Exception { if (futurePeerConnection.isSuccess()) { - // successfully created a connection to the other peer - final PeerConnection peerConnection = futurePeerConnection.object(); - - // send the message - send(peerConnection, peer.peerBean(), peer.connectionBean(), futureResponse); + requestHandler.sendTCP(fpc.channelCreator(), null); } else { futureResponse.failed(fpc); } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java index 8d69eecb9..eb636bb5d 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -7,19 +7,21 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; import net.tomp2p.futures.FutureDiscover; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +//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 TestNATForwarding implements Serializable { final static private Random RND = new Random(42); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 28867e3d2..542ba88b5 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -35,7 +35,10 @@ * @author Thomas Bocek * */ -//@Ignore +//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 TestNATLocal implements Serializable { private static final long serialVersionUID = 1L; diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index bfd9bc523..8bdd93497 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -2,7 +2,6 @@ import java.io.IOException; import java.io.Serializable; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Random; @@ -12,6 +11,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import net.tomp2p.connection.PeerConnection; @@ -27,7 +27,10 @@ import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; -//@Ignore +//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 TestNATRelay implements Serializable { private static final long serialVersionUID = 1L; diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index 6ec9aca57..9c7b201a4 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -9,6 +9,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import net.tomp2p.connection.PeerConnection; @@ -17,7 +18,6 @@ import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDiscover; import net.tomp2p.nat.FutureNAT; import net.tomp2p.nat.PeerBuilderNAT; @@ -40,6 +40,11 @@ * @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 TestNATStress implements Serializable { final static private Random RND = new Random(42); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index c3ba735fb..e1fdd8941 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -6,6 +6,12 @@ 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; @@ -13,12 +19,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - /** * Add the following lines to sudoers username ALL=(ALL) NOPASSWD: * /nat-net.sh username ALL=(ALL) NOPASSWD: /usr/bin/ip @@ -35,7 +35,10 @@ * @author Thomas Bocek * */ -//@Ignore +//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 TestNATTypeDetection implements Serializable { private static final long serialVersionUID = 1L; diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java index 8de9cd649..4fdd16540 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java @@ -7,6 +7,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import net.tomp2p.dht.FuturePut; @@ -23,6 +24,10 @@ import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.storage.Data; +//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 TestUPNP implements Serializable { final static private Random RND = new Random(42); From 4453f4f5b443f6b3b8175607e9e845089f0a47f9 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 14 Oct 2015 18:58:23 +0200 Subject: [PATCH 101/135] fixing buffer requests --- .../net/tomp2p/connection/Dispatcher.java | 16 +-- .../java/net/tomp2p/nat/PeerBuilderNAT.java | 39 +++++- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 2 +- .../main/java/net/tomp2p/relay/Forwarder.java | 13 +- .../main/java/net/tomp2p/relay/RelayRPC.java | 13 +- .../test/java/net/tomp2p/relay/TestSlow.java | 127 ++++++++++++++++++ nat/src/test/resources/logback.xml | 2 +- 7 files changed, 191 insertions(+), 21 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/relay/TestSlow.java diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index a412afcaf..0869a094d 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -183,14 +183,13 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa //handle late responses from pending requests - final FutureResponse lateRequests = getPendingRequests().get(message.messageId()); - if(lateRequests!=null) { - lateRequests.response(message); + final FutureResponse lateRequest = getPendingRequests().get(message.messageId()); + if(lateRequest != null) { + LOG.debug("Handing lates request. {}", message); + lateRequest.response(message); Message responseMessage = DispatchHandler.createResponseMessage(message, Type.OK, peerBeanMaster.serverPeerAddress()); response(ctx, responseMessage); - } else { - Message responseMessage = DispatchHandler.createResponseMessage(message, Type.NOT_FOUND, peerBeanMaster.serverPeerAddress()); - response(ctx, responseMessage); + return; } if (!message.isRequest()) { @@ -198,11 +197,6 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa ctx.fireChannelRead(message); return; } - - //NAT reflection, translate back - if(message.sender().isNet4Private()) { - //message.sender(). - } Responder responder = new DirectResponder(ctx, message); final DispatchHandler myHandler = associatedHandler(message); diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index 9a3d238d3..6db7fd1f6 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -57,6 +57,8 @@ public void onShutdown() {} private BootstrapBuilder bootstrapBuilder; private Integer peerMapUpdateIntervalSeconds; + private Integer bufferTimeoutSeconds; + private Integer bufferSize; private static final int DEFAULT_NUMBER_OF_HOLEP_HOLES = 3; private int holePNumberOfHoles = DEFAULT_NUMBER_OF_HOLEP_HOLES; @@ -139,6 +141,33 @@ public PeerBuilderNAT executorService(ExecutorService executorService) { this.executorService = executorService; return this; } + + public Integer peerMapUpdateIntervalSeconds() { + return peerMapUpdateIntervalSeconds; + } + + public PeerBuilderNAT peerMapUpdateIntervalSeconds(Integer peerMapUpdateIntervalSeconds) { + this.peerMapUpdateIntervalSeconds = peerMapUpdateIntervalSeconds; + return this; + } + + public Integer bufferTimeoutSeconds() { + return bufferTimeoutSeconds; + } + + public PeerBuilderNAT bufferTimeoutSeconds(Integer bufferTimeoutSeconds) { + this.bufferTimeoutSeconds = bufferTimeoutSeconds; + return this; + } + + public Integer bufferSize() { + return bufferSize; + } + + public PeerBuilderNAT bufferSize(Integer bufferSize) { + this.bufferSize = bufferSize; + return this; + } public PeerNAT start() { @@ -158,6 +187,14 @@ public PeerNAT start() { peerMapUpdateIntervalSeconds = 60; } + if(bufferTimeoutSeconds == null) { + bufferTimeoutSeconds = 60; + } + + if(bufferSize == null) { + bufferSize = 16; + } + final NATUtils natUtils = new NATUtils(); final RconRPC rconRPC = new RconRPC(peer); final HolePRPC holePunchRPC = new HolePRPC(peer); @@ -166,7 +203,7 @@ public PeerNAT start() { peer.peerBean().holePNumberOfHoles(holePNumberOfHoles); peer.peerBean().holePNumberOfPunches(holePNumberOfPunches); - final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC); + final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC, bufferTimeoutSeconds, bufferSize); if(executorService == null) { executorService = Executors.newSingleThreadExecutor(); diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index 92dc4ca89..b852f725a 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -41,7 +41,7 @@ public class PeerNAT { private final DistributedRelay distributedRelay; private boolean relayMaintenance; private BootstrapBuilder bootstrapBuilder; - private int peerMapUpdateIntervalSeconds; + private int peerMapUpdateIntervalSeconds; PeerNAT(Peer peer, NATUtils natUtils, RelayRPC relayRPC, boolean manualPorts, DistributedRelay distributedRelay, boolean relayMaintenance, BootstrapBuilder bootstrapBuilder, int peerMapUpdateIntervalSeconds) { diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 99fb11814..340ae72a6 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -44,14 +44,16 @@ public class Forwarder extends DispatchHandler { private final List buffer = Collections.synchronizedList(new ArrayList()); - private int capacity = 16; + final private int bufferSize; + final private int bufferTimeoutSeconds; private long lastAccess = System.currentTimeMillis(); - private int bufferTimeSec = 60; - public Forwarder(Peer peer, PeerConnection unreachablePeerConnection, boolean isSlow) { + public Forwarder(Peer peer, PeerConnection unreachablePeerConnection, boolean isSlow, int bufferTimeoutSeconds, int bufferSize) { super(peer.peerBean(), peer.connectionBean()); this.unreachablePeerConnection = unreachablePeerConnection; this.isSlow = isSlow; + this.bufferTimeoutSeconds = bufferTimeoutSeconds; + this.bufferSize = bufferSize; } private FutureDone forwardOrBuffer(final Message requestMessage) { @@ -270,18 +272,21 @@ public final void setPeerMap(List> peerMap, Messag } private void addToBuffer(Message requestMessage) { + LOG.debug("add msg on peer {}, {}"+System.identityHashCode(this), peerBean().serverPeerAddress(), requestMessage); buffer.add(requestMessage); checkSend(); } private void checkSend() { - if(buffer.size() > capacity || lastAccess + (bufferTimeSec * 1000) < System.currentTimeMillis()) { + LOG.debug("check buffer on peer {}"+System.identityHashCode(this), peerBean().serverPeerAddress()); + if(buffer.size() > 0 && (buffer.size() > bufferSize || lastAccess + (bufferTimeoutSeconds * 1000) < System.currentTimeMillis())) { forwardMessages(buffer); lastAccess = System.currentTimeMillis(); } } private void forwardMessages(List buffer2) { + LOG.debug("empty buffer on peer {}"+System.identityHashCode(this), peerBean().serverPeerAddress()); final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_4); // always keep the connection open diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index e8eb62df1..d1564d9a4 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -81,14 +81,19 @@ public class RelayRPC extends DispatchHandler { * @param rconRPC the reverse connection RPC * @return */ - public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC) { + + final private int bufferTimeoutSeconds; + final private int bufferSize; + + public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, int bufferTimeoutSeconds, int bufferSize) { super(peer.peerBean(), peer.connectionBean()); this.peer = peer; //this.servers = new ConcurrentHashMap(); //this.clients = new ConcurrentHashMap(); this.rconRPC = rconRPC; this.holePunchRPC = holePRPC; - + this.bufferTimeoutSeconds = bufferTimeoutSeconds; + this.bufferSize = bufferSize; // register this handler register(RPC.Commands.RELAY.getNr()); @@ -255,7 +260,7 @@ private void handleSetup(Message message, final PeerConnection unreachablePeerCo // arrives) dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, this, command.getNr()); } else { - final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow()); + final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow(), bufferTimeoutSeconds, bufferSize); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, forwarder, command.getNr()); } } @@ -360,6 +365,7 @@ private void handleBuffer(final Message message, Responder responder) throws Inv List buffered = RelayUtils.decomposeCompositeBuffer( message.buffer(0).buffer(), message.recipient().createSocketTCP(), message.sender().createSocketTCP(), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); + LOG.debug("got {} messages", buffered.size()); for(Message msg:buffered) { DispatchHandler dh = connectionBean().dispatcher().associatedHandler(msg); //TODO: add a custom responder and respond to the address found in the message @@ -381,6 +387,7 @@ public FutureDone response(Message responseMessage) { responseMessage.recipient(responseMessage.recipient().changeAddress(sender.getAddress()).changePorts(sender.getPort(), sender.getPort())); + LOG.debug("send late reply {}", responseMessage); FutureResponse fr = RelayUtils.connectAndSend(peer(), responseMessage); final FutureDone fd = new FutureDone(); fr.addListener(new BaseFutureAdapter() { diff --git a/nat/src/test/java/net/tomp2p/relay/TestSlow.java b/nat/src/test/java/net/tomp2p/relay/TestSlow.java new file mode 100644 index 000000000..0b51215bd --- /dev/null +++ b/nat/src/test/java/net/tomp2p/relay/TestSlow.java @@ -0,0 +1,127 @@ +package net.tomp2p.relay; + +import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import net.tomp2p.connection.PeerConnection; +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.BaseFutureAdapter; +import net.tomp2p.futures.FutureBootstrap; +import net.tomp2p.futures.FutureDirect; +import net.tomp2p.futures.FutureDone; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.PeerBuilder; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.rpc.ObjectDataReply; + +public class TestSlow { + + private Peer reachable = null; + private Peer slow = null; + private Peer master = null; + private Peer[] peers = null; + private PeerNAT reachableNAT = null; + + private static final int PORTS = 4001; + private static final int NUMBER_OF_NODES = 5; + private static final Random RND = new Random(); + + @Before + public void setupRelay() throws Exception { + // setup test peers + peers = UtilsNAT.createNodes(NUMBER_OF_NODES, RND, PORTS); + master = peers[0]; + reachable = peers[4]; + UtilsNAT.perfectRouting(peers); + // every peer must own a PeerNAT in order to be able to be a relay and + // set up a reverse connection + for (Peer peer : peers) { + if (peer.equals(reachable)) { + reachableNAT = new PeerBuilderNAT(peer).start(); + } else { + new PeerBuilderNAT(peer).bufferTimeoutSeconds(10).start(); + } + } + + // Test setting up relay peers + slow = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORTS + 1).start(); + PeerAddress pa = slow.peerBean().serverPeerAddress(); + pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true).changeSlow(true); + slow.peerBean().serverPeerAddress(pa); + + // find neighbors + FutureBootstrap futureBootstrap = slow.bootstrap().peerAddress(peers[0].peerAddress()).start(); + futureBootstrap.awaitUninterruptibly(); + Assert.assertTrue(futureBootstrap.isSuccess()); + + // setup relay + PeerNAT uNat = new PeerBuilderNAT(slow).bufferTimeoutSeconds(10).peerMapUpdateIntervalSeconds(10).start(); + uNat.startRelay(master.peerAddress()); + Thread.sleep(5000); + + // Check if flags are set correctly + Assert.assertTrue(slow.peerAddress().isRelayed()); + Assert.assertFalse(slow.peerAddress().isFirewalledTCP()); + Assert.assertFalse(slow.peerAddress().isFirewalledUDP()); + Assert.assertTrue(slow.peerAddress().isSlow()); + + System.err.println("master = " + master.peerAddress()); + System.err.println("reachable = " + reachable.peerAddress()); + System.err.println("unreachable = " + slow.peerAddress()); + } + + @Test + public void testSlow() throws Exception { + System.err.println("testReverseConnection() start!"); + + final String requestString = "This is a test String"; + final String replyString = "SUCCESS HIT"; + final CountDownLatch cLatch = new CountDownLatch(1); + + slow.objectDataReply(new ObjectDataReply() { + + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + if (requestString.equals((String) request)) { + System.err.println("received: " + (String) request); + cLatch.countDown(); + } + return replyString; + } + }); + + FutureDirect fd = reachable.sendDirect(slow.peerAddress()).object(requestString).start(); + fd.awaitUninterruptibly(); + + checkFail(cLatch); + + System.err.println("testReverseConnection() end!"); + } + + private void checkFail(final CountDownLatch cLatch) throws InterruptedException { + if (!cLatch.await(25, TimeUnit.SECONDS)) { + Assert.fail("The test method did not complete successfully! Still has " + cLatch.getCount() + " counts."); + } + } + + @After + public void shutdown() { + System.err.println("shutdown initiated!"); + for (Peer ele : peers) { + BaseFuture bf = ele.shutdown(); + bf.awaitUninterruptibly(); + } + BaseFuture bf = slow.shutdown(); + bf.awaitUninterruptibly(); + System.err.println("shutdown done!"); + } +} diff --git a/nat/src/test/resources/logback.xml b/nat/src/test/resources/logback.xml index 43bf89d08..f78f74829 100644 --- a/nat/src/test/resources/logback.xml +++ b/nat/src/test/resources/logback.xml @@ -45,7 +45,7 @@ --> - + From 254e7dc695f3241c529ab803b96e03c821f4a590 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 11:38:46 +0200 Subject: [PATCH 102/135] fixing issue #122 --- .../tomp2p/p2p/builder/DiscoverBuilder.java | 9 ++- .../src/main/java/net/tomp2p/rpc/PingRPC.java | 81 +++++++++++-------- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 66274d1ac..c5c52b88f 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -32,6 +32,7 @@ import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FutureResponse; import net.tomp2p.futures.Futures; +import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerReachable; import net.tomp2p.peers.Number160; @@ -255,7 +256,13 @@ public void operationComplete(FutureDone future) throws Exception { @Override public void operationComplete(FutureResponse future) throws Exception { PeerAddress serverAddress = peer.peerBean().serverPeerAddress(); - if (futureResponseTCP.isSuccess()) { + if (futureResponseTCP.isSuccess() && futureResponseTCP.responseMessage().type() == Type.NOT_FOUND) { + //this was a ping to myself. This is pointless + futureDiscover.failed("FutureDiscover to yourself", + futureResponseTCP); + return; + } + else if (futureResponseTCP.isSuccess()) { //now we know our internal address, set it as it could be a wrong one, e.g. 127.0.0.1 serverAddress = serverAddress.changeAddress(futureResponseTCP.responseMessage().recipient().inetAddress()); diff --git a/core/src/main/java/net/tomp2p/rpc/PingRPC.java b/core/src/main/java/net/tomp2p/rpc/PingRPC.java index 38b2dbe80..0e9e7a347 100644 --- a/core/src/main/java/net/tomp2p/rpc/PingRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/PingRPC.java @@ -312,45 +312,60 @@ public void handleResponse(final Message message, PeerConnection peerConnection, // probe if (message.type() == Type.REQUEST_3) { LOG.debug("Respond to probing. Firing message to {}.", message.sender()); - responseMessage = createResponseMessage(message, Type.OK); - - if (message.isUdp()) { - connectionBean().reservation().create(1, 0).addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureChannelCreator future) throws Exception { - if (future.isSuccess()) { - LOG.debug("Fire UDP to {}.", message.sender()); - FutureResponse futureResponse = fireUDP(message.sender(), future.channelCreator(), - connectionBean().channelServer().channelServerConfiguration()); - Utils.addReleaseListener(future.channelCreator(), futureResponse); - } else { - Utils.addReleaseListener(future.channelCreator()); - LOG.warn("handleResponse for REQUEST_3 failed (UDP) {}", future.failedReason()); - } + if(message.isSendSelf()) { + responseMessage = createResponseMessage(message, Type.NOT_FOUND); + LOG.warn("Sending probe ping request to yourself? If those are two different peers, messages may be dropped"); + if(!message.sender().inetAddress().equals(message.recipient().inetAddress())) { + if(message.sender().peerId().equals(message.recipient().peerId())) { + LOG.warn("You seem to use the same peerId for different peers. This may result in dropped messages"); } - }); + } } else { - connectionBean().reservation().create(0, 1).addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(final FutureChannelCreator future) throws Exception { - if (future.isSuccess()) { - LOG.debug("Fire TCP to {}.", message.sender()); - FutureResponse futureResponse = fireTCP(message.sender(), future.channelCreator(), - connectionBean().channelServer().channelServerConfiguration()); - Utils.addReleaseListener(future.channelCreator(), futureResponse); - } else { - Utils.addReleaseListener(future.channelCreator()); - LOG.warn("handleResponse for REQUEST_3 failed (TCP) {}", future.failedReason()); + responseMessage = createResponseMessage(message, Type.OK); + + if (message.isUdp()) { + connectionBean().reservation().create(1, 0).addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureChannelCreator future) throws Exception { + if (future.isSuccess()) { + LOG.debug("Fire UDP to {}.", message.sender()); + FutureResponse futureResponse = fireUDP(message.sender(), future.channelCreator(), + connectionBean().channelServer().channelServerConfiguration()); + Utils.addReleaseListener(future.channelCreator(), futureResponse); + } else { + Utils.addReleaseListener(future.channelCreator()); + LOG.warn("handleResponse for REQUEST_3 failed (UDP) {}", future.failedReason()); + } } - } - }); + }); + } else { + connectionBean().reservation().create(0, 1).addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(final FutureChannelCreator future) throws Exception { + if (future.isSuccess()) { + LOG.debug("Fire TCP to {}.", message.sender()); + FutureResponse futureResponse = fireTCP(message.sender(), future.channelCreator(), + connectionBean().channelServer().channelServerConfiguration()); + Utils.addReleaseListener(future.channelCreator(), futureResponse); + } else { + Utils.addReleaseListener(future.channelCreator()); + LOG.warn("handleResponse for REQUEST_3 failed (TCP) {}", future.failedReason()); + } + } + }); + } } } else if (message.type() == Type.REQUEST_2) { // discover LOG.debug("Respond to discovering. Found {}.", message.sender()); - responseMessage = createResponseMessage(message, Type.OK); - final int port = message.senderSocket().getPort(); - responseMessage.neighborsSet(createNeighborSet(message.sender())); - responseMessage.intValue(port); + if(message.isSendSelf()) { + responseMessage = createResponseMessage(message, Type.NOT_FOUND); + LOG.warn("Sending discover ping request to yourself? If those are two different peers, messages may be dropped"); + } else { + responseMessage = createResponseMessage(message, Type.OK); + final int port = message.senderSocket().getPort(); + responseMessage.neighborsSet(createNeighborSet(message.sender())); + responseMessage.intValue(port); + } } else if (message.type() == Type.REQUEST_1 || message.type() == Type.REQUEST_4) { // regular // ping LOG.debug("Respond to regular ping {}.", message.sender()); From 4f0f384b618d41b137745c509fab5b543e859a59 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 13:54:11 +0200 Subject: [PATCH 103/135] Added Slow Peer example --- .../net/tomp2p/connection/Dispatcher.java | 6 +- .../net/tomp2p/connection/PeerConnection.java | 7 ++ .../net/tomp2p/connection/PeerCreator.java | 4 +- .../net/tomp2p/connection/RequestHandler.java | 4 +- .../java/net/tomp2p/connection/Sender.java | 3 +- .../tomp2p/p2p/builder/DiscoverBuilder.java | 1 + core/src/main/java/net/tomp2p/rpc/RPC.java | 8 ++ .../net/tomp2p/examples/ExampleBuffer.java | 60 +++++++++++++ .../net/tomp2p/relay/DistributedRelay.java | 12 ++- .../main/java/net/tomp2p/relay/Forwarder.java | 6 +- .../net/tomp2p/relay/PeerMapUpdateTask.java | 13 ++- .../main/java/net/tomp2p/relay/RelayRPC.java | 84 ++++++++++--------- .../java/net/tomp2p/relay/RelayUtils.java | 7 +- .../test/java/net/tomp2p/relay/TestSlow.java | 7 +- 14 files changed, 160 insertions(+), 62 deletions(-) create mode 100644 examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 0869a094d..943368377 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -183,7 +183,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa //handle late responses from pending requests - final FutureResponse lateRequest = getPendingRequests().get(message.messageId()); + final FutureResponse lateRequest = findAndRemovePendingRequests(message.messageId()); if(lateRequest != null) { LOG.debug("Handing lates request. {}", message); lateRequest.response(message); @@ -477,8 +477,8 @@ public void run() { /** * @return all pending requests */ - public Map getPendingRequests() { - return pendingRequests; + public FutureResponse findAndRemovePendingRequests(final int messageId) { + return pendingRequests.get(messageId); } public boolean responsibleFor(Number160 peerId) { diff --git a/core/src/main/java/net/tomp2p/connection/PeerConnection.java b/core/src/main/java/net/tomp2p/connection/PeerConnection.java index d224aca6e..8094825ee 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerConnection.java +++ b/core/src/main/java/net/tomp2p/connection/PeerConnection.java @@ -219,4 +219,11 @@ public boolean equals(Object obj) { } return remotePeer.equals(p.remotePeer); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("pconn: "); + sb.append(remotePeer); + return sb.toString(); + } } diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index b67d1ce0d..ca77b2dde 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -148,7 +148,9 @@ public FutureDone shutdown() { return futureServerDone.done(); } // shutdown the timer - connectionBean.timer().shutdown(); + for(Runnable runner: connectionBean.timer().shutdownNow()) { + runner.run(); + } LOG.debug("Shutting down client..."); connectionBean.reservation().shutdown().addListener(new BaseFutureAdapter>() { diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index fdb205f8d..a97b8cd7e 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -284,13 +284,13 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo // RPC.Commands.RCON message on top of it. Therefore the response // type will never be the same Type as the one the user initially // used (e.g. DIRECT_DATA). - if (responseMessage.command() != RPC.Commands.RCON.getNr() + /*if (responseMessage.command() != RPC.Commands.RCON.getNr() && message.recipient().isRelayed() != responseMessage.sender().isRelayed()) { String msg = "Response message [" + responseMessage + "] sent has a different relay flag than we sent with request message [" + this.message + "]. Recipient (" + message.recipient().isRelayed() + ") / Sender (" + responseMessage.sender().isRelayed() + ")"; LOG.warn(msg); - } + }*/ //NAT reflection, change it back, as this will be stored in our peer map that may be queried from other peers if(message.recipientReflected() != null) { diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index 8f8748d28..f562363e9 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -612,7 +612,8 @@ private PeerSocketAddress prepareRelaySend(final Message message, final PeerSock //we don't have any internal address information in peersocketaddress -> TODO while(!psa.isEmpty()) { PeerSocketAddress ps = psa.remove(random.nextInt(psa.size())); - if(ps.inetAddress().equals(peerBean.serverPeerAddress().peerSocketAddress().inetAddress())) { + if(peerBean.serverPeerAddress().isPortForwarding() && + ps.inetAddress().equals(peerBean.serverPeerAddress().peerSocketAddress().inetAddress())) { continue; } message.recipientRelay(message.recipient().changePeerSocketAddress(ps).changeRelayed(true)); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index c5c52b88f..39881da8f 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -302,6 +302,7 @@ else if (futureResponseTCP.isSuccess()) { LOG.info("manual ports, change it to: {}", serverAddress); } else if(expectManualForwarding) { final PeerAddress serverAddressOrig = serverAddress; + serverAddress = serverAddress.changePortForwarding(true); serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); serverAddress = serverAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); peer.peerBean().serverPeerAddress(serverAddress); diff --git a/core/src/main/java/net/tomp2p/rpc/RPC.java b/core/src/main/java/net/tomp2p/rpc/RPC.java index d83e5aac6..f1647af9f 100644 --- a/core/src/main/java/net/tomp2p/rpc/RPC.java +++ b/core/src/main/java/net/tomp2p/rpc/RPC.java @@ -37,6 +37,14 @@ public byte getNr() { public static Commands find(int nr) { return values()[nr]; } + + public static String toString(int nr) { + return values()[nr].name(); + } + + public String toString() { + return values()[ordinal()].name(); + } } } diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java new file mode 100644 index 000000000..f9c7a824f --- /dev/null +++ b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java @@ -0,0 +1,60 @@ +package net.tomp2p.examples; + +import java.util.Date; + +import net.tomp2p.dht.PeerBuilderDHT; +import net.tomp2p.dht.PeerDHT; +import net.tomp2p.futures.FutureBootstrap; +import net.tomp2p.futures.FutureDirect; +import net.tomp2p.nat.PeerBuilderNAT; +import net.tomp2p.nat.PeerNAT; +import net.tomp2p.p2p.PeerBuilder; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.rpc.ObjectDataReply; +import net.tomp2p.storage.Data; + +public class ExampleBuffer { + public static void main(String[] args) throws Exception { + final Number160 idP1 = Number160.createHash("p1"); + final Number160 idP2 = Number160.createHash("p2"); + final Number160 idP3 = Number160.createHash("p3"); + PeerDHT relay = new PeerBuilderDHT(new PeerBuilder(idP1).ports(1234).start()).start(); + PeerDHT requester = new PeerBuilderDHT(new PeerBuilder(idP2).ports(1235).start()).start(); + PeerDHT slow = new PeerBuilderDHT(new PeerBuilder(idP3).ports(1236).start()).start(); + + PeerNAT pn1 = new PeerBuilderNAT(relay.peer()).bufferTimeoutSeconds(30).start(); + PeerNAT pn2 = new PeerBuilderNAT(requester.peer()).bufferTimeoutSeconds(30).start(); + + PeerAddress pa = slow.peerBean().serverPeerAddress(); + pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true).changeSlow(true); + slow.peerBean().serverPeerAddress(pa); + + // find neighbors + FutureBootstrap futureBootstrap = slow.peer().bootstrap().peerAddress(relay.peerAddress()).start(); + futureBootstrap.awaitUninterruptibly(); + + // setup relay + PeerNAT pn3 = new PeerBuilderNAT(slow.peer()).peerMapUpdateIntervalSeconds(30).start(); + pn3.startRelay(relay.peerAddress()); + + slow.peer().objectDataReply(new ObjectDataReply() { + + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + System.err.println("received: " + (String) request); + return "REPLY"; + } + }); + + Thread.sleep(3000); + System.err.println("RPC to ("+new Date()+") "+slow.peerAddress()); + FutureDirect fd = requester.peer().sendDirect(slow.peerAddress()).object("REQUEST").start(); + fd.awaitUninterruptibly(); + System.err.println("GOT ("+new Date()+"): "+fd.object()); + + relay.shutdown(); + requester.shutdown(); + slow.shutdown(); + } +} diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 8ac5263e7..b7c1e7b2a 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -19,6 +19,7 @@ import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDone; +import net.tomp2p.futures.FutureResponse; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.peers.Number160; @@ -352,7 +353,16 @@ public void operationComplete(FutureBootstrap future) // send the peer map to the relays List> peerMapVerified = relayRPC.peer().peerBean().peerMap().peerMapVerified(); for (final Map.Entry entry : activeClients().entrySet()) { - relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + FutureResponse fr = relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + //if we have buffered messages, send reply + fr.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if(future.isSuccess()) { + relayRPC.handleBuffer(future.responseMessage()); + } + } + }); LOG.debug("send peermap to {}", entry.getKey()); } } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 340ae72a6..6d159234c 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -272,13 +272,13 @@ public final void setPeerMap(List> peerMap, Messag } private void addToBuffer(Message requestMessage) { - LOG.debug("add msg on peer {}, {}"+System.identityHashCode(this), peerBean().serverPeerAddress(), requestMessage); + LOG.debug("add msg on peer {}, {}", peerBean().serverPeerAddress(), requestMessage); buffer.add(requestMessage); checkSend(); } private void checkSend() { - LOG.debug("check buffer on peer {}"+System.identityHashCode(this), peerBean().serverPeerAddress()); + LOG.debug("check buffer on peer {}", peerBean().serverPeerAddress()); if(buffer.size() > 0 && (buffer.size() > bufferSize || lastAccess + (bufferTimeoutSeconds * 1000) < System.currentTimeMillis())) { forwardMessages(buffer); lastAccess = System.currentTimeMillis(); @@ -286,7 +286,7 @@ private void checkSend() { } private void forwardMessages(List buffer2) { - LOG.debug("empty buffer on peer {}"+System.identityHashCode(this), peerBean().serverPeerAddress()); + LOG.debug("empty buffer on peer {}", peerBean().serverPeerAddress()); final Message envelope = createMessage(unreachablePeerConnection.remotePeer(), RPC.Commands.RELAY.getNr(), Type.REQUEST_4); // always keep the connection open diff --git a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java index 2e26fb3d0..5fe3e59c4 100644 --- a/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java +++ b/nat/src/main/java/net/tomp2p/relay/PeerMapUpdateTask.java @@ -10,6 +10,7 @@ import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; +import net.tomp2p.futures.FutureResponse; import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; @@ -62,7 +63,17 @@ public void operationComplete(FutureBootstrap future) // send the peer map to the relays List> peerMapVerified = relayRPC.peer().peerBean().peerMap().peerMapVerified(); for (final Map.Entry entry : distributedRelay.activeClients().entrySet()) { - relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + FutureResponse fr = relayRPC.sendPeerMap(entry.getKey(), entry.getValue(), peerMapVerified); + //if we have buffered messages, send reply + fr.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if(future.isSuccess()) { + relayRPC.handleBuffer(future.responseMessage()); + } + + } + }); LOG.debug("send peermap to {}", entry.getKey()); } } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index d1564d9a4..a376be220 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -171,7 +171,8 @@ public void handleResponse(final Message message, PeerConnection peerConnection, } else if (message.type() == Type.REQUEST_4 && message.command() == RPC.Commands.RELAY.getNr()) { // An unreachable peer requests the buffer at the relay peer // or a buffer is transmitted to the unreachable peer directly - handleBuffer(message, responder); + handleBuffer(message); + responder.response(createResponseMessage(message, Type.OK)); } else { throw new IllegalArgumentException("Message content is wrong"); } @@ -244,23 +245,27 @@ private void handleSetup(Message message, final PeerConnection unreachablePeerCo //now we can add this peer to the map, as we have now set the flag //its TCP, we have a connection to this peer, so mark it as first hand peerBean().notifyPeerFound(unreachablePeerConnectionCopy.remotePeer(), null, unreachablePeerConnectionCopy, null); + final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow(), bufferTimeoutSeconds, bufferSize); for (Commands command : RPC.Commands.values()) { if (command == RPC.Commands.RCON) { // We must register the rconRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. + LOG.debug("register rcon for {}, {}",command.toString(), message); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, rconRPC, command.getNr()); } else if (command == RPC.Commands.HOLEP) { // We must register the holePunchRPC for every unreachable peer that // we serve as a relay. Without this registration, no reverse // connection setup is possible. + LOG.debug("register holepunching for {}, {}",command.toString(), message); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, holePunchRPC, command.getNr()); } else if (command == RPC.Commands.RELAY) { // Register this class to handle all relay messages (currently used when a slow message // arrives) + LOG.debug("register this for {}, {}",command.toString(), message); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, this, command.getNr()); } else { - final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow(), bufferTimeoutSeconds, bufferSize); + LOG.debug("register forwarder for {}, {}",command.toString(), message); dispatcher().registerIoHandler(peer.peerID(), unreachablePeerId, forwarder, command.getNr()); } } @@ -360,8 +365,11 @@ private void handleMap(Message message, Responder responder) { } } - private void handleBuffer(final Message message, Responder responder) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { + public void handleBuffer(final Message message) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { //the unreachable peer gets the buffered messages + if(message.bufferList().isEmpty()) { + return; + } List buffered = RelayUtils.decomposeCompositeBuffer( message.buffer(0).buffer(), message.recipient().createSocketTCP(), message.sender().createSocketTCP(), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); @@ -369,45 +377,41 @@ private void handleBuffer(final Message message, Responder responder) throws Inv for(Message msg:buffered) { DispatchHandler dh = connectionBean().dispatcher().associatedHandler(msg); //TODO: add a custom responder and respond to the address found in the message - dh.forwardMessage(msg, null, new Responder() { - - @Override - public void responseFireAndForget() {} + dh.forwardMessage(msg, null, createResponder(peer, msg.sender().peerSocketAddress())); + } + + } + + private static Responder createResponder(final Peer peer, final PeerSocketAddress sender) { + return new Responder() { + + @Override + public void responseFireAndForget() {} + + @Override + public FutureDone response(final Message responseMessage) { - @Override - public FutureDone response(Message responseMessage) { - // this contains the real sender - Collection peerSocketAddresses = message.peerSocketAddresses(); - final InetSocketAddress sender; - if (!peerSocketAddresses.isEmpty()) { - sender = PeerSocketAddress.createSocketTCP(peerSocketAddresses.iterator().next()); - } else { - sender = new InetSocketAddress(0); + responseMessage.recipient(responseMessage.recipient().changeAddress(sender.inetAddress()).changePorts(sender.tcpPort(), sender.udpPort())); + + LOG.debug("send late reply {}", responseMessage); + final FutureResponse fr = RelayUtils.connectAndSend(peer, responseMessage); + final FutureDone fd = new FutureDone(); + fr.addListener(new BaseFutureAdapter() { + + @Override + public void operationComplete(FutureResponse future) + throws Exception { + fd.done(); } - - responseMessage.recipient(responseMessage.recipient().changeAddress(sender.getAddress()).changePorts(sender.getPort(), sender.getPort())); - - LOG.debug("send late reply {}", responseMessage); - FutureResponse fr = RelayUtils.connectAndSend(peer(), responseMessage); - final FutureDone fd = new FutureDone(); - fr.addListener(new BaseFutureAdapter() { - - @Override - public void operationComplete(FutureResponse future) - throws Exception { - fd.done(); - } - }); - return fd; - } - - @Override - public void failed(Type type, String reason) { - LOG.error("could not sent to peer. {}", reason); - } - }); - } - responder.response(createResponseMessage(message, Type.OK)); + }); + return fd; + } + + @Override + public void failed(Type type, String reason) { + LOG.error("could not sent to peer. {}", reason); + } + }; } } diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 80913b69d..6a3f4f6dc 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -29,7 +29,6 @@ import net.tomp2p.connection.SignatureFactory; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; -import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.futures.FutureResponse; import net.tomp2p.message.Buffer; import net.tomp2p.message.Decoder; @@ -270,9 +269,9 @@ public static FutureResponse connectAndSend(final Peer peer, final Message messa final RequestHandler requestHandler = new RequestHandler(futureResponse, peer.peerBean(), peer.connectionBean(), peer.connectionBean().channelServer().channelServerConfiguration()); final FutureChannelCreator fpc = peer.connectionBean().reservation().create(0, 1); - fpc.addListener(new BaseFutureAdapter() { - public void operationComplete(final FuturePeerConnection futurePeerConnection) throws Exception { - if (futurePeerConnection.isSuccess()) { + fpc.addListener(new BaseFutureAdapter() { + public void operationComplete(final FutureChannelCreator futureChannelCreator) throws Exception { + if (futureChannelCreator.isSuccess()) { requestHandler.sendTCP(fpc.channelCreator(), null); } else { futureResponse.failed(fpc); diff --git a/nat/src/test/java/net/tomp2p/relay/TestSlow.java b/nat/src/test/java/net/tomp2p/relay/TestSlow.java index 0b51215bd..35f140c21 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestSlow.java +++ b/nat/src/test/java/net/tomp2p/relay/TestSlow.java @@ -29,7 +29,6 @@ public class TestSlow { private Peer slow = null; private Peer master = null; private Peer[] peers = null; - private PeerNAT reachableNAT = null; private static final int PORTS = 4001; private static final int NUMBER_OF_NODES = 5; @@ -45,11 +44,7 @@ public void setupRelay() throws Exception { // every peer must own a PeerNAT in order to be able to be a relay and // set up a reverse connection for (Peer peer : peers) { - if (peer.equals(reachable)) { - reachableNAT = new PeerBuilderNAT(peer).start(); - } else { - new PeerBuilderNAT(peer).bufferTimeoutSeconds(10).start(); - } + new PeerBuilderNAT(peer).bufferTimeoutSeconds(10).start(); } // Test setting up relay peers From 3ed21dea9997e39406b2ea7c0f44c5e42ef49de6 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 15:39:00 +0200 Subject: [PATCH 104/135] fixed slow peer example --- .../ChannelServerConfiguration.java | 18 + .../net/tomp2p/connection/ConnectionBean.java | 1 + .../net/tomp2p/connection/Dispatcher.java | 15 +- .../net/tomp2p/connection/PeerConnection.java | 16 +- .../net/tomp2p/connection/PeerCreator.java | 2 +- .../java/net/tomp2p/connection/Sender.java | 13 +- .../net/tomp2p/connection/TimeoutFactory.java | 16 + core/src/main/java/net/tomp2p/p2p/Peer.java | 6 +- .../test/java/net/tomp2p/rpc/TestDirect.java | 2 +- .../net/tomp2p/examples/ExampleBuffer.java | 10 +- .../examples/ExamplePersistentConnection.java | 2 +- .../tomp2p/examples/SeedNodeForTesting.java | 88 -- .../java/net/tomp2p/examples/TomP2PTests.java | 764 ------------------ .../java/net/tomp2p/nat/PeerBuilderNAT.java | 31 +- .../main/java/net/tomp2p/relay/RelayRPC.java | 8 +- 15 files changed, 113 insertions(+), 879 deletions(-) delete mode 100644 examples/src/main/java/net/tomp2p/examples/SeedNodeForTesting.java delete mode 100644 examples/src/main/java/net/tomp2p/examples/TomP2PTests.java diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java b/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java index 782022a2e..3c88f4005 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServerConfiguration.java @@ -32,6 +32,7 @@ public class ChannelServerConfiguration implements ConnectionConfiguration { private boolean disableBind = false; private int idleTCPMillis = ConnectionBean.DEFAULT_TCP_IDLE_MILLIS; + private int idleTCPSlowMillis = ConnectionBean.DEFAULT_TCP_IDLE_SLOW_MILLIS; private int idleUDPMillis = ConnectionBean.DEFAULT_UDP_IDLE_MILLIS; private int connectionTimeoutTCPMillis = ConnectionBean.DEFAULT_CONNECTION_TIMEOUT_TCP; private int slowResponseTimeoutSeconds = ConnectionBean.DEFAULT_SLOW_RESPONSE_TIMEOUT_SECONDS; @@ -128,6 +129,23 @@ public ChannelServerConfiguration idleTCPMillis(final int idleTCPMillis) { this.idleTCPMillis = idleTCPMillis; return this; } + + /** + * @return The time that a connection can be idle before it is considered not active for short-lived connections + */ + public int idleTCPSlowMillis() { + return idleTCPSlowMillis; + } + + /** + * @param idleTCPSeconds + * The time that a connection can be idle before its considered not active for short-lived connections + * @return This class + */ + public ChannelServerConfiguration idleTCPSlowMillis(final int idleTCPSlowMillis) { + this.idleTCPSlowMillis = idleTCPSlowMillis; + return this; + } /** * @return The time that a connection can be idle before its considered not active for short-lived connections diff --git a/core/src/main/java/net/tomp2p/connection/ConnectionBean.java b/core/src/main/java/net/tomp2p/connection/ConnectionBean.java index b503fedab..aebc5fcd3 100644 --- a/core/src/main/java/net/tomp2p/connection/ConnectionBean.java +++ b/core/src/main/java/net/tomp2p/connection/ConnectionBean.java @@ -32,6 +32,7 @@ public class ConnectionBean { //non-final to be able to adapt changes public static int DEFAULT_TCP_IDLE_MILLIS = 5 * 1000; + public static int DEFAULT_TCP_IDLE_SLOW_MILLIS = 30 * 1000; public static int DEFAULT_UDP_IDLE_MILLIS = 5 * 1000; public static int DEFAULT_CONNECTION_TIMEOUT_TCP = 3 * 1000; public static int DEFAULT_SLOW_RESPONSE_TIMEOUT_SECONDS = 60; diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 943368377..35fe3ac04 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -68,7 +68,6 @@ public class Dispatcher extends SimpleChannelInboundHandler { private final int p2pID; private final PeerBean peerBeanMaster; - private final int heartBeatMillis; //use locks instead copy on write as testcases became really slow final private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock(); @@ -83,7 +82,7 @@ public class Dispatcher extends SimpleChannelInboundHandler { */ final private Map pendingRequests = new ConcurrentHashMap(); - + final private ChannelServerConfiguration csc; /** * Creates a dispatcher. * @@ -92,10 +91,10 @@ public class Dispatcher extends SimpleChannelInboundHandler { * @param peerBeanMaster * . */ - public Dispatcher(final int p2pID, final PeerBean peerBeanMaster, final int heartBeatMillis) { + public Dispatcher(final int p2pID, final PeerBean peerBeanMaster, ChannelServerConfiguration csc) { this.p2pID = p2pID; this.peerBeanMaster = peerBeanMaster; - this.heartBeatMillis = heartBeatMillis; + this.csc = csc; } public PeerBean peerBean() { @@ -181,7 +180,11 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa return; } - + if(message.sender().isSlow() && message.isKeepAlive()) { + //reset timer + TimeoutFactory.resetTimeout(ctx, csc.idleTCPSlowMillis()); + } + //handle late responses from pending requests final FutureResponse lateRequest = findAndRemovePendingRequests(message.messageId()); if(lateRequest != null) { @@ -203,7 +206,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa if (myHandler != null) { boolean isUdp = ctx.channel() instanceof DatagramChannel; LOG.debug("About to respond to request message {}.", message); - PeerConnection peerConnection = new PeerConnection(message.sender(), new DefaultChannelPromise(ctx.channel()).setSuccess(), heartBeatMillis); + PeerConnection peerConnection = new PeerConnection(message.sender(), new DefaultChannelPromise(ctx.channel()).setSuccess(), 0, 0); myHandler.forwardMessage(message, isUdp ? null : peerConnection, responder); } else { message.release(); diff --git a/core/src/main/java/net/tomp2p/connection/PeerConnection.java b/core/src/main/java/net/tomp2p/connection/PeerConnection.java index 8094825ee..e41d80356 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerConnection.java +++ b/core/src/main/java/net/tomp2p/connection/PeerConnection.java @@ -31,13 +31,14 @@ public class PeerConnection { final private Map map; final private FutureDone closeFuture; final private int heartBeatMillis; + final private int idleTCP; // these may be called from different threads, but they will never be called concurrently within this library private volatile ChannelFuture channelFuture; private PeerConnection(Semaphore oneConnection, PeerAddress remotePeer, ChannelCreator cc, boolean initiator, Map map, FutureDone closeFuture, - int heartBeatMillis, ChannelFuture channelFuture) { + int heartBeatMillis, int idleTCP, ChannelFuture channelFuture) { this.oneConnection = oneConnection; this.remotePeer = remotePeer; this.cc = cc; @@ -45,6 +46,7 @@ private PeerConnection(Semaphore oneConnection, PeerAddress remotePeer, ChannelC this.map = map; this.closeFuture = closeFuture; this.heartBeatMillis = heartBeatMillis; + this.idleTCP = idleTCP; this.channelFuture = channelFuture; } @@ -59,10 +61,11 @@ private PeerConnection(Semaphore oneConnection, PeerAddress remotePeer, ChannelC * @param heartBeatMillis * The heart beat in milliseconds */ - public PeerConnection(PeerAddress remotePeer, ChannelCreator cc, int heartBeatMillis) { + public PeerConnection(PeerAddress remotePeer, ChannelCreator cc, int heartBeatMillis, int idleTCP) { this.remotePeer = remotePeer; this.cc = cc; this.heartBeatMillis = heartBeatMillis; + this.idleTCP = idleTCP; this.initiator = true; this.oneConnection = new Semaphore(1); this.map = new LinkedHashMap(); @@ -79,12 +82,13 @@ public PeerConnection(PeerAddress remotePeer, ChannelCreator cc, int heartBeatMi * @param heartBeatMillis * The heart beat in milliseconds */ - public PeerConnection(PeerAddress remotePeer, ChannelFuture channelFuture, int heartBeatMillis) { + public PeerConnection(PeerAddress remotePeer, ChannelFuture channelFuture, int heartBeatMillis, int idleTCP) { this.remotePeer = remotePeer; this.channelFuture = channelFuture; addCloseListener(channelFuture); this.cc = null; this.heartBeatMillis = heartBeatMillis; + this.idleTCP = idleTCP; this.initiator = false; this.oneConnection = new Semaphore(1); this.map = new LinkedHashMap(); @@ -100,6 +104,10 @@ public PeerConnection channelFuture(ChannelFuture channelFuture) { public int heartBeatMillis() { return heartBeatMillis; } + + public int idleTCP() { + return idleTCP; + } public ChannelFuture channelFuture() { return channelFuture; @@ -194,7 +202,7 @@ public boolean isOpen() { } public PeerConnection changeRemotePeer(PeerAddress remotePeer) { - return new PeerConnection(oneConnection, remotePeer, cc, initiator, map, closeFuture, heartBeatMillis, channelFuture); + return new PeerConnection(oneConnection, remotePeer, cc, initiator, map, closeFuture, heartBeatMillis, idleTCP, channelFuture); } @Override diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index ca77b2dde..e5d8d3d9f 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -94,7 +94,7 @@ public PeerCreator(final int p2pId, final Number160 peerId, final KeyPair keyPai workerGroup = new NioEventLoopGroup(0, new DefaultThreadFactory(ConnectionBean.THREAD_NAME + "worker-client/server - ")); bossGroup = new NioEventLoopGroup(2, new DefaultThreadFactory(ConnectionBean.THREAD_NAME + "boss - ")); - Dispatcher dispatcher = new Dispatcher(p2pId, peerBean, channelServerConfiguration.heartBeatMillis()); + Dispatcher dispatcher = new Dispatcher(p2pId, peerBean, channelServerConfiguration); final ChannelServer channelServer = new ChannelServer(bossGroup, workerGroup, channelServerConfiguration, dispatcher, peerBean.peerStatusListeners(), timer); diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index f562363e9..e02123773 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -402,10 +402,17 @@ private ChannelFuture sendTCPCreateChannel(InetSocketAddress recipient, ChannelC ChannelHandler handler, TimeoutFactory timeoutHandler, int connectTimeoutMillis, FutureResponse futureResponse) { final Map> handlers; + + HeartBeat heartBeat = null; + int timeout = -1; + if (peerConnection != null) { + heartBeat = new HeartBeat(peerConnection.heartBeatMillis(), TimeUnit.MILLISECONDS, pingBuilderFactory); + timeout = peerConnection.idleTCP(); + } if (timeoutHandler != null) { handlers = new LinkedHashMap>(); - handlers.put("timeout0", new Pair(null, timeoutHandler.idleStateHandlerTomP2P())); + handlers.put("timeout0", new Pair(null, timeoutHandler.idleStateHandlerTomP2P(timeout))); handlers.put("timeout1", new Pair(null, timeoutHandler.timeHandler())); } else { handlers = new LinkedHashMap>(); @@ -427,10 +434,8 @@ private ChannelFuture sendTCPCreateChannel(InetSocketAddress recipient, ChannelC if (timeoutHandler != null) { handlers.put("handler", new Pair(null, handler)); } - - HeartBeat heartBeat = null; + if (peerConnection != null) { - heartBeat = new HeartBeat(peerConnection.heartBeatMillis(), TimeUnit.MILLISECONDS, pingBuilderFactory); handlers.put("heartbeat", new Pair(null, heartBeat)); } diff --git a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java index 9d61276bc..80916987d 100644 --- a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java +++ b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java @@ -73,6 +73,15 @@ public TimeoutFactory(final FutureResponse futureResponse, final int timeoutMill public ChannelHandler idleStateHandlerTomP2P() { return new IdleStateHandlerTomP2P(timeoutMillis); } + + public ChannelHandler idleStateHandlerTomP2P(int timeoutMillis) { + if(timeoutMillis <= 0) { + return new IdleStateHandlerTomP2P(this.timeoutMillis); + } + else { + return new IdleStateHandlerTomP2P(timeoutMillis); + } + } /** * @return Two handlers, one default Netty that will call the second handler @@ -89,6 +98,13 @@ public static void removeTimeout(ChannelHandlerContext ctx) { ctx.channel().pipeline().remove("timeout1"); } } + + public static void resetTimeout(ChannelHandlerContext ctx, int timeoutMillis) { + if (ctx.channel().pipeline().names().contains("timeout0")) { + ChannelHandler old = ctx.channel().pipeline().get("timeout0"); + ctx.channel().pipeline().replace(old, "timeout0-0", new IdleStateHandlerTomP2P(timeoutMillis)); + } + } /** * The timeout handler that gets called from the {@link IdleStateHandlerTomP2P}. diff --git a/core/src/main/java/net/tomp2p/p2p/Peer.java b/core/src/main/java/net/tomp2p/p2p/Peer.java index e3b34f927..0c9ecf2cd 100644 --- a/core/src/main/java/net/tomp2p/p2p/Peer.java +++ b/core/src/main/java/net/tomp2p/p2p/Peer.java @@ -232,7 +232,7 @@ public void objectDataReply(final ObjectDataReply objectDataReply) { } public FuturePeerConnection createPeerConnection(final PeerAddress destination) { - return createPeerConnection(destination, PeerConnection.HEART_BEAT_MILLIS); + return createPeerConnection(destination, PeerConnection.HEART_BEAT_MILLIS, ConnectionBean.DEFAULT_TCP_IDLE_MILLIS); } /** @@ -250,7 +250,7 @@ public FuturePeerConnection createPeerConnection(final PeerAddress destination) * @return A class that needs to be passed to those methods that should use the already open connection. If the * connection could not be reserved, maybe due to a shutdown, null is returned. */ - public FuturePeerConnection createPeerConnection(final PeerAddress destination, final int heartBeatMillis) { + public FuturePeerConnection createPeerConnection(final PeerAddress destination, final int heartBeatMillis, final int idleTCP) { final FuturePeerConnection futureDone = new FuturePeerConnection(destination); final FutureChannelCreator fcc = connectionBean().reservation().createPermanent(1); fcc.addListener(new BaseFutureAdapter() { @@ -258,7 +258,7 @@ public FuturePeerConnection createPeerConnection(final PeerAddress destination, public void operationComplete(final FutureChannelCreator future) throws Exception { if (future.isSuccess()) { final ChannelCreator cc = fcc.channelCreator(); - final PeerConnection peerConnection = new PeerConnection(destination, cc, heartBeatMillis); + final PeerConnection peerConnection = new PeerConnection(destination, cc, heartBeatMillis, idleTCP); futureDone.done(peerConnection); } else { futureDone.failed(future); diff --git a/core/src/test/java/net/tomp2p/rpc/TestDirect.java b/core/src/test/java/net/tomp2p/rpc/TestDirect.java index c7605d28a..8933d26c5 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestDirect.java +++ b/core/src/test/java/net/tomp2p/rpc/TestDirect.java @@ -240,7 +240,7 @@ public Object reply(PeerAddress sender, Object request) throws Exception { return "yes"; } }); - FuturePeerConnection peerConnection = sender.createPeerConnection(recv1.peerAddress(), 8000); + FuturePeerConnection peerConnection = sender.createPeerConnection(recv1.peerAddress(), 8000, 2000); ccohTCP.reset(); ccohUDP.reset(); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java index f9c7a824f..6adf12556 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java @@ -2,6 +2,7 @@ import java.util.Date; +import net.tomp2p.connection.ChannelServerConfiguration; import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; import net.tomp2p.futures.FutureBootstrap; @@ -12,7 +13,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.rpc.ObjectDataReply; -import net.tomp2p.storage.Data; public class ExampleBuffer { public static void main(String[] args) throws Exception { @@ -21,7 +21,9 @@ public static void main(String[] args) throws Exception { final Number160 idP3 = Number160.createHash("p3"); PeerDHT relay = new PeerBuilderDHT(new PeerBuilder(idP1).ports(1234).start()).start(); PeerDHT requester = new PeerBuilderDHT(new PeerBuilder(idP2).ports(1235).start()).start(); - PeerDHT slow = new PeerBuilderDHT(new PeerBuilder(idP3).ports(1236).start()).start(); + ChannelServerConfiguration csc = PeerBuilder.createDefaultChannelServerConfiguration(); + csc.idleTCPSlowMillis(35 * 1000); + PeerDHT slow = new PeerBuilderDHT(new PeerBuilder(idP3).channelServerConfiguration(csc).ports(1236).start()).start(); PeerNAT pn1 = new PeerBuilderNAT(relay.peer()).bufferTimeoutSeconds(30).start(); PeerNAT pn2 = new PeerBuilderNAT(requester.peer()).bufferTimeoutSeconds(30).start(); @@ -35,7 +37,7 @@ public static void main(String[] args) throws Exception { futureBootstrap.awaitUninterruptibly(); // setup relay - PeerNAT pn3 = new PeerBuilderNAT(slow.peer()).peerMapUpdateIntervalSeconds(30).start(); + PeerNAT pn3 = new PeerBuilderNAT(slow.peer()).peerMapUpdateIntervalSeconds(30).heartBeatMillis(30 * 1000).idleTCP(35 * 1000).start(); pn3.startRelay(relay.peerAddress()); slow.peer().objectDataReply(new ObjectDataReply() { @@ -47,8 +49,8 @@ public Object reply(PeerAddress sender, Object request) throws Exception { } }); - Thread.sleep(3000); System.err.println("RPC to ("+new Date()+") "+slow.peerAddress()); + Thread.sleep(3000); FutureDirect fd = requester.peer().sendDirect(slow.peerAddress()).object("REQUEST").start(); fd.awaitUninterruptibly(); System.err.println("GOT ("+new Date()+"): "+fd.object()); diff --git a/examples/src/main/java/net/tomp2p/examples/ExamplePersistentConnection.java b/examples/src/main/java/net/tomp2p/examples/ExamplePersistentConnection.java index c101d5b25..dd3de5304 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExamplePersistentConnection.java +++ b/examples/src/main/java/net/tomp2p/examples/ExamplePersistentConnection.java @@ -102,7 +102,7 @@ public Object reply(final PeerAddress sender, final Object request) throws Excep + ccohTCP.total()+ "/"+ccohUDP.total()); // keep the connection for 20s alive. Setting -1 means to keep it open as long as possible - FuturePeerConnection futurePeerConnection = peer1.createPeerConnection(peer2.peerAddress(), timeout); + FuturePeerConnection futurePeerConnection = peer1.createPeerConnection(peer2.peerAddress(), timeout, timeout/2); fd = peer1.sendDirect(futurePeerConnection).object(sentObject).start(); System.out.println("send " + sentObject); diff --git a/examples/src/main/java/net/tomp2p/examples/SeedNodeForTesting.java b/examples/src/main/java/net/tomp2p/examples/SeedNodeForTesting.java deleted file mode 100644 index 2b38ee576..000000000 --- a/examples/src/main/java/net/tomp2p/examples/SeedNodeForTesting.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package net.tomp2p.examples; - -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.rpc.ObjectDataReply; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Used for testing with {@link TomP2PTests} - */ -public class SeedNodeForTesting { - private static Peer peer = null; - private static boolean running = true; - private static final Logger log = LoggerFactory.getLogger(SeedNodeForTesting.class); - - public static void main(String[] args) throws Exception { - try { - Number160 peerId = Number160.createHash(TomP2PTests.BOOTSTRAP_NODE_ID); - /* PeerMapConfiguration pmc = new PeerMapConfiguration(peerId).peerNoVerification(); - PeerMap pm = new PeerMap(pmc);*/ - peer = new PeerBuilder(peerId).ports(TomP2PTests.BOOTSTRAP_NODE_PORT)/*.peerMap(pm)*/.start(); - peer.objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - log.trace("received request: ", request.toString()); - return "pong"; - } - }); - - new PeerBuilderDHT(peer).start(); - new PeerBuilderNAT(peer).start(); - - log.debug("SeedNode started."); - new Thread(new Runnable() { - - @Override - public void run() { - while (running) { - for (PeerAddress pa : peer.peerBean().peerMap().all()) { - log.debug("peer online:" + pa); - } - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - return; - } - } - - } - }).start(); - - } catch (Exception e) { - if (peer != null) - peer.shutdown().awaitUninterruptibly(); - } - } - - public static void stop() { - running = false; - if(peer!=null ) { - peer.shutdown().awaitUninterruptibly(); - } - peer = null; - } -} diff --git a/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java b/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java deleted file mode 100644 index 94fe73aa1..000000000 --- a/examples/src/main/java/net/tomp2p/examples/TomP2PTests.java +++ /dev/null @@ -1,764 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package net.tomp2p.examples; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.Random; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import net.tomp2p.connection.Bindings; -import net.tomp2p.connection.ChannelClientConfiguration; -import net.tomp2p.connection.PeerConnection; -import net.tomp2p.connection.StandardProtocolFamily; -import net.tomp2p.dht.FutureGet; -import net.tomp2p.dht.FuturePut; -import net.tomp2p.dht.FutureRemove; -import net.tomp2p.dht.PeerBuilderDHT; -import net.tomp2p.dht.PeerDHT; -import net.tomp2p.examples.utils.Repeat; -import net.tomp2p.examples.utils.RepeatRule; -import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.BaseFutureAdapter; -import net.tomp2p.futures.BaseFutureListener; -import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDirect; -import net.tomp2p.futures.FutureDiscover; -import net.tomp2p.futures.FuturePeerConnection; -import net.tomp2p.nat.FutureNAT; -import net.tomp2p.nat.PeerBuilderNAT; -import net.tomp2p.nat.PeerNAT; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.relay.RelayCallback; -import net.tomp2p.rpc.ObjectDataReply; -import net.tomp2p.storage.Data; - -/** - * Test bootstrapping, DHT operations like put/get/add/remove and sendDirect in both LAN and WAN environment - * Test scenarios in direct connection, auto port forwarding or relay mode. - *

- * To start a bootstrap node code use the {@link net.tomp2p.examples.SeedNodeForTesting} class. - *

- * To configure your test environment edit the static fields for id, IP and port. - * In the configure method and the connectionType you can define your test scenario. - */ -//@Ignore -public class TomP2PTests { - private enum ConnectionType { - UNKNOWN, DIRECT, NAT, RELAY - } - - private static final Logger log = LoggerFactory.getLogger(TomP2PTests.class); - - final static String BOOTSTRAP_NODE_ID = "seed"; - private final static String BOOTSTRAP_NODE_IP = "127.0.0.1"; - final static int BOOTSTRAP_NODE_PORT = 5000; - - // If you want to test in one specific connection mode define it directly, otherwise use UNKNOWN - private static final ConnectionType FORCED_CONNECTION_TYPE = ConnectionType.DIRECT; - - private static final PeerAddress BOOTSTRAP_NODE_ADDRESS; - - static { - try { - BOOTSTRAP_NODE_ADDRESS = new PeerAddress( - Number160.createHash(BOOTSTRAP_NODE_ID), - BOOTSTRAP_NODE_IP, BOOTSTRAP_NODE_PORT, BOOTSTRAP_NODE_PORT); - } catch (UnknownHostException e) { - throw new RuntimeException(e); - } - } - - // Use to stress tests by repeating them - private static final int STRESS_TEST_COUNT = 10; - - private Peer peer; - private PeerDHT peer1DHT; - private PeerDHT peer2DHT; - private int client1Port; - private int client2Port; - private ConnectionType resolvedConnectionType; - public @Rule RepeatRule repeatRule = new RepeatRule(); - - @Before - public void setUp() { - client1Port = 7777; - client2Port = 7778; - } - - @After - public void tearDown() { - if (peer1DHT != null) { - BaseFuture future = peer1DHT.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - } - if (peer2DHT != null) { - BaseFuture future = peer2DHT.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - } - if (peer != null) { - BaseFuture future = peer.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - } - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void bootstrapInUnknownMode() throws Exception { - if (FORCED_CONNECTION_TYPE == ConnectionType.UNKNOWN) { - peer = bootstrapInUnknownMode(client1Port); - assertNotNull(peer); - } - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testBootstrapDirectConnection() throws Exception { - if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { - peer = bootstrapDirectConnection(client1Port); - assertNotNull(peer); - } - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testBootstrapWithPortForwarding() throws Exception { - if (FORCED_CONNECTION_TYPE == ConnectionType.NAT) { - peer = bootstrapWithPortForwarding(client1Port); - assertNotNull(peer); - } - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testBootstrapInRelayMode() throws Exception { - if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) { - peer = bootstrapInRelayMode(client1Port); - assertNotNull(peer); - } - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testPut() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start(); - futurePut.awaitUninterruptibly(); - assertTrue(futurePut.isSuccess()); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testPutGet() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut = peer1DHT.put(Number160.createHash("key")).data(new Data("hallo")).start(); - futurePut.awaitUninterruptibly(); - assertTrue(futurePut.isSuccess()); - - peer2DHT = getDHTPeer(client2Port); - FutureGet futureGet = peer2DHT.get(Number160.createHash("key")).start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertEquals("hallo", futureGet.data().object()); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testAdd() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); - futurePut1.awaitUninterruptibly(); - assertTrue(futurePut1.isSuccess()); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testAddGet() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")) - .start(); - futurePut1.awaitUninterruptibly(); - assertTrue(futurePut1.isSuccess()); - - FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")) - .start(); - futurePut2.awaitUninterruptibly(); - assertTrue(futurePut2.isSuccess()); - - - peer2DHT = getDHTPeer(client2Port); - FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testAddGetWithReconnect() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); - futurePut1.awaitUninterruptibly(); - assertTrue(futurePut1.isSuccess()); - FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start(); - futurePut2.awaitUninterruptibly(); - assertTrue(futurePut2.isSuccess()); - - peer2DHT = getDHTPeer(client2Port); - FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - - // shut down peer2 - BaseFuture future = peer2DHT.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - - // start up peer2 - peer2DHT = getDHTPeer(client2Port); - futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - - futureGet = peer1DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - - // shut down both - future = peer2DHT.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - future = peer1DHT.shutdown(); - future.awaitUninterruptibly(); - future.awaitListenersUninterruptibly(); - - // start up both - peer1DHT = getDHTPeer(client1Port); - futureGet = peer1DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - - peer2DHT = getDHTPeer(client2Port); - futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo1"))); - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 2); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testParallelStartupWithPutGet() throws IOException, ClassNotFoundException, InterruptedException { - - PeerMapConfiguration pmc1 = new PeerMapConfiguration(Number160.createHash( "peer1" ) ).peerNoVerification(); - PeerMap pm1 = new PeerMap(pmc1); - - PeerDHT peer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer1")).ports(3006).peerMap( pm1 ).start()).start(); - - PeerMapConfiguration pmc2 = new PeerMapConfiguration(Number160.createHash( "peer2" ) ).peerNoVerification(); - PeerMap pm2 = new PeerMap(pmc2); - - PeerDHT peer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer2")).ports(3007).peerMap( pm2 ).start()).start(); - - PeerAddress masterPeerAddress = new PeerAddress(Number160.createHash(BOOTSTRAP_NODE_ID), - BOOTSTRAP_NODE_IP, BOOTSTRAP_NODE_PORT, - BOOTSTRAP_NODE_PORT); - - // start both at the same time - BaseFuture fb1 = peer1.peer().bootstrap().peerAddress(masterPeerAddress).start(); - BaseFuture fb2 = peer2.peer().bootstrap().peerAddress(masterPeerAddress).start(); - - final AtomicBoolean peer1Done = new AtomicBoolean(); - final AtomicBoolean peer2Done = new AtomicBoolean(); - - fb1.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - peer1Done.set(true); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - - fb2.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - peer2Done.set(true); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - - while (!peer1Done.get() || !peer2Done.get()) - Thread.sleep(100); - - // both are started up - System.err.println(fb1.failedReason()); - Assert.assertTrue(fb1.isSuccess()); - System.err.println(fb2.failedReason()); - Assert.assertTrue(fb2.isSuccess()); - - // peer1 put data - FuturePut fp = peer1.put(Number160.ONE).object("test").start().awaitUninterruptibly(); - Assert.assertTrue(fp.isSuccess()); - - // both get data - FutureGet fg1 = peer1.get(Number160.ONE).start().awaitUninterruptibly(); - Assert.assertTrue(fg1.isSuccess()); - Assert.assertEquals("test", fg1.data().object()); - FutureGet fg2 = peer2.get(Number160.ONE).start().awaitUninterruptibly(); - Assert.assertTrue(fg2.isSuccess()); - Assert.assertEquals("test", fg2.data().object()); - - // shutdown both - peer1.shutdown().awaitUninterruptibly().awaitListenersUninterruptibly(); - peer2.shutdown().awaitUninterruptibly().awaitListenersUninterruptibly(); - - // start both again at the same time - peer1 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer1")).ports(3005).start()).start(); - peer2 = new PeerBuilderDHT(new PeerBuilder(Number160.createHash("peer2")).ports(3006).start()).start(); - - fb1 = peer1.peer().bootstrap().peerAddress(masterPeerAddress).start(); - fb2 = peer2.peer().bootstrap().peerAddress(masterPeerAddress).start(); - - peer1Done.set(false); - peer2Done.set(false); - - final PeerDHT _peer1 = peer1; - fb1.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - peer1Done.set(true); - - // when peer1 is ready it gets the data - final FutureGet fg = _peer1.get(Number160.ONE).start(); - fg.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - Assert.assertTrue(fg.isSuccess()); - Assert.assertEquals("test", fg.data().object()); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - - final PeerDHT _peer2 = peer2; - fb2.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - peer2Done.set(true); - - // when peer2 is ready it gets the data - final FutureGet fg = _peer2.get(Number160.ONE).start(); - fg.addListener(new BaseFutureListener() { - @Override - public void operationComplete(BaseFuture future) throws Exception { - Assert.assertTrue(fg.isSuccess()); - Assert.assertEquals("test", fg.data().object()); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - } - - @Override - public void exceptionCaught(Throwable t) throws Exception { - } - }); - - while (!peer1Done.get() || !peer2Done.get()) - Thread.sleep(100); - - // both are started up - System.err.println(fb1.failedReason()); - Assert.assertTrue(fb1.isSuccess()); - System.err.println(fb2.failedReason()); - Assert.assertTrue(fb2.isSuccess()); - - - // get data again for both - fg1 = peer1.get(Number160.ONE).start().awaitUninterruptibly(); - Assert.assertTrue(fg1.isSuccess()); - Assert.assertEquals("test", fg1.data().object()); - - fg2 = peer2.get(Number160.ONE).start().awaitUninterruptibly(); - Assert.assertTrue(fg2.isSuccess()); - Assert.assertEquals("test", fg2.data().object()); - - peer1.shutdown().awaitUninterruptibly(); - peer2.shutdown().awaitUninterruptibly(); - } - - @Test - @Repeat(STRESS_TEST_COUNT) - public void testAddRemove() throws Exception { - - if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { - SeedNodeForTesting.main(null); - } - - peer1DHT = getDHTPeer(client1Port); - FuturePut futurePut1 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo1")).start(); - futurePut1.awaitUninterruptibly(); - futurePut1.awaitListenersUninterruptibly(); - assertTrue(futurePut1.isSuccess()); - - FuturePut futurePut2 = peer1DHT.add(Number160.createHash("locationKey")).data(new Data("hallo2")).start(); - futurePut2.awaitUninterruptibly(); - futurePut2.awaitListenersUninterruptibly(); - assertTrue(futurePut2.isSuccess()); - - - peer2DHT = getDHTPeer(client2Port); - Number160 contentKey = new Data("hallo1").hash(); - FutureRemove futureRemove = peer2DHT.remove(Number160.createHash("locationKey")).contentKey(contentKey).start(); - futureRemove.awaitUninterruptibly(); - futureRemove.awaitListenersUninterruptibly(); - - // We don't test futureRemove.isSuccess() as this API does not fit well to that operation, - // it might change in future to something like foundAndRemoved and notFound - // See discussion at: https://github.com/tomp2p/TomP2P/issues/57#issuecomment-62069840 - - assertTrue(futureRemove.isSuccess()); - - FutureGet futureGet = peer2DHT.get(Number160.createHash("locationKey")).all().start(); - futureGet.awaitUninterruptibly(); - assertTrue(futureGet.isSuccess()); - if (!futureGet.dataMap().values().contains(new Data("hallo2"))) { - log.error("raw data has the value, the evaluated not!"); - } - - assertTrue(futureGet.dataMap().values().contains(new Data("hallo2"))); - assertTrue(futureGet.dataMap().values().size() == 1); - - if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { - SeedNodeForTesting.stop(); - } - } - - - // The sendDirect operation fails in port forwarding mode because most routers does not support NAT reflections. - // So if both clients are behind NAT they cannot send direct message to each other. - // That will probably be fixed in a future version of TomP2P - @Test - @Repeat(STRESS_TEST_COUNT) - public void testSendDirectBetweenLocalPeers() throws Exception { - if (FORCED_CONNECTION_TYPE != ConnectionType.NAT && resolvedConnectionType != ConnectionType.RELAY) { - peer1DHT = getDHTPeer(client1Port); - peer2DHT = getDHTPeer(client2Port); - - final CountDownLatch countDownLatch = new CountDownLatch(1); - - final StringBuilder result = new StringBuilder(); - peer2DHT.peer().objectDataReply(new ObjectDataReply() { - @Override - public Object reply(PeerAddress sender, Object request) throws Exception { - countDownLatch.countDown(); - result.append(String.valueOf(request)); - return "pong"; - } - }); - - FuturePeerConnection futurePeerConnection = peer1DHT.peer().createPeerConnection(peer2DHT.peer() - .peerAddress(), 500); - FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start(); - futureDirect.awaitUninterruptibly(); - - - countDownLatch.await(3, TimeUnit.SECONDS); - if (countDownLatch.getCount() > 0) - Assert.fail("The test method did not complete successfully!"); - - assertEquals("hallo", result.toString()); - assertTrue(futureDirect.isSuccess()); - log.debug(futureDirect.object().toString()); - assertEquals("pong", futureDirect.object()); - } - } - - // This test should always succeed as we use the bootstrap node as receiver. - // A node can send a message to another peer which is not in the same LAN. - @Test - @Repeat(STRESS_TEST_COUNT) - public void testSendDirectToSeedNode() throws Exception { - peer1DHT = getDHTPeer(client1Port); - FuturePeerConnection futurePeerConnection = - peer1DHT.peer().createPeerConnection(BOOTSTRAP_NODE_ADDRESS, 500); - FutureDirect futureDirect = peer1DHT.peer().sendDirect(futurePeerConnection).object("hallo").start(); - futureDirect.awaitUninterruptibly(); - assertTrue(futureDirect.isSuccess()); - assertEquals("pong", futureDirect.object()); - } - - private Peer bootstrapDirectConnection(int clientPort) { - Peer peer = null; - Number160 peerId = new Number160(new Random(43L)); - PeerMapConfiguration pmc = new PeerMapConfiguration(peerId).peerNoVerification(); - PeerMap pm = new PeerMap(pmc); - ChannelClientConfiguration cc = PeerBuilder.createDefaultChannelClientConfiguration(); - cc.maxPermitsTCP(100); - cc.maxPermitsUDP(100); - - try { - peer = new PeerBuilder(peerId).bindings(getBindings()).channelClientConfiguration(cc).peerMap(pm) - .ports(clientPort).start(); - } catch (IOException e) { - log.warn("Discover with direct connection failed. Exception = " + e.getMessage()); - e.printStackTrace(); - return null; - } - - FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureDiscover.awaitUninterruptibly(); - if (futureDiscover.isSuccess()) { - log.info("Discover with direct connection successful. Address = " + futureDiscover.peerAddress()); - - FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureBootstrap.awaitUninterruptibly(); - if (futureBootstrap.isSuccess()) { - return peer; - } else { - log.warn("Bootstrap failed. Reason = " + futureBootstrap.failedReason()); - peer.shutdown().awaitUninterruptibly(); - return null; - } - } else { - log.warn("Discover with direct connection failed. Reason = " + futureDiscover.failedReason()); - peer.shutdown().awaitUninterruptibly(); - return null; - } - } - - private Peer bootstrapWithPortForwarding(int clientPort) { - Number160 peerId = new Number160(new Random(43L)); - Peer peer = null; - try { - peer = new PeerBuilder(peerId).bindings(getBindings()).behindFirewall().ports(clientPort).start(); - } catch (IOException e) { - log.warn("Discover with automatic port forwarding failed. Exception = " + e.getMessage()); - e.printStackTrace(); - return null; - } - - PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); - FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - FutureNAT futureNAT = peerNAT.portForwarding(futureDiscover); - futureNAT.awaitUninterruptibly(); - if (futureNAT.isSuccess()) { - log.info("Automatic port forwarding is setup. Now we do a futureDiscover again. Address = " - + futureNAT.peerAddress()); - futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureDiscover.awaitUninterruptibly(); - if (futureDiscover.isSuccess()) { - log.info("Discover with automatic port forwarding was successful. Address = " + futureDiscover.peerAddress()); - - FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureBootstrap.awaitUninterruptibly(); - if (futureBootstrap.isSuccess()) { - return peer; - } else { - log.warn("Bootstrap failed. Reason = " + futureBootstrap.failedReason()); - peer.shutdown().awaitUninterruptibly(); - return null; - } - } else { - log.warn("Discover with automatic port forwarding failed. Reason = " + futureDiscover.failedReason()); - peer.shutdown().awaitUninterruptibly(); - return null; - } - } else { - log.warn("StartSetupPortforwarding failed. Reason = " + futureNAT.failedReason()); - peer.shutdown().awaitUninterruptibly(); - return null; - } - } - - private Peer bootstrapInRelayMode(int clientPort) throws InterruptedException { - Number160 peerId = new Number160(new Random(43L)); - final Peer peer; - try { - peer = new PeerBuilder(peerId).bindings(getBindings()).behindFirewall().ports(clientPort).start(); - } catch (IOException e) { - log.error("Bootstrap using relay failed. Exception " + e.getMessage()); - e.printStackTrace(); - return null; - } - - final PeerNAT peerNAT = new PeerBuilderNAT(peer).relayCallback(new RelayCallback() { - - @Override - public void onRelayRemoved(PeerAddress relay, PeerConnection object) { - log.info("Relay was removed. Address = " + relay); - } - - @Override - public void onRelayAdded(PeerAddress relay, PeerConnection object) { - log.info("Bootstrap using relay was successful. Address = " + relay); - } - - @Override - public void onNoMoreRelays(int activeRelays) { - log.info("No more relays found. Active relays: " + activeRelays); - } - - @Override - public void onFullRelays(int activeRelays) { - log.info("All relays found. Active relays: " + activeRelays); - } - - @Override - public void onFailure(Exception e) { - log.error("error", e); - } - - @Override - public void onShutdown() { - peer.shutdown().awaitUninterruptibly(); - } - }).start(); - final FutureDiscover futureDiscover = peer.discover().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - FutureNAT futureNAT = peerNAT.portForwarding(futureDiscover); - - futureNAT.addListener(new BaseFutureAdapter() { - - @Override - public void operationComplete(FutureNAT future) throws Exception { - if(future.isFailed()) { - peerNAT.startRelay(futureDiscover.reporter()); - } - } - }); - - //make the return also a future - Thread.sleep(5000); - - FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(BOOTSTRAP_NODE_ADDRESS).start(); - futureBootstrap.awaitUninterruptibly(); - if (futureBootstrap.isSuccess()) { - return peer; - } else { - log.warn("Bootstrap failed. Reason = " + futureBootstrap.failedReason()); - peer.shutdown(); - return null; - } - } - - private Peer bootstrapInUnknownMode(int clientPort) throws InterruptedException { - resolvedConnectionType = ConnectionType.DIRECT; - Peer peer = bootstrapDirectConnection(clientPort); - if (peer != null) - return peer; - - resolvedConnectionType = ConnectionType.NAT; - peer = bootstrapWithPortForwarding(clientPort); - if (peer != null) - return peer; - - resolvedConnectionType = ConnectionType.RELAY; - peer = bootstrapInRelayMode(clientPort); - if (peer != null) - return peer; - else - log.error("Bootstrapping in all modes failed. Is bootstrap node with address " + BOOTSTRAP_NODE_ADDRESS + "running?"); - - resolvedConnectionType = null; - return peer; - } - - private PeerDHT getDHTPeer(int clientPort) throws InterruptedException { - Peer peer; - if (FORCED_CONNECTION_TYPE == ConnectionType.DIRECT) { - peer = bootstrapDirectConnection(clientPort); - } - else if (FORCED_CONNECTION_TYPE == ConnectionType.NAT) { - peer = bootstrapWithPortForwarding(clientPort); - } - else if (FORCED_CONNECTION_TYPE == ConnectionType.RELAY) { - peer = bootstrapInRelayMode(clientPort); - } - else { - peer = bootstrapInUnknownMode(clientPort); - } - - if (peer == null) - Assert.fail("Bootstrapping failed." + - " forcedConnectionType= " + FORCED_CONNECTION_TYPE + - " resolvedConnectionType= " + resolvedConnectionType + "." + - " Is bootstrap node with address " + BOOTSTRAP_NODE_ADDRESS + "running?"); - - return new PeerBuilderDHT(peer).start(); - } - - private Bindings getBindings() { - Bindings bindings = new Bindings(); - bindings.addProtocol(StandardProtocolFamily.INET); - return bindings; - } -} diff --git a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java index 6db7fd1f6..da5521999 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerBuilderNAT.java @@ -59,6 +59,8 @@ public void onShutdown() {} private Integer peerMapUpdateIntervalSeconds; private Integer bufferTimeoutSeconds; private Integer bufferSize; + private Integer heartBeatMillis; + private Integer idleTCP; private static final int DEFAULT_NUMBER_OF_HOLEP_HOLES = 3; private int holePNumberOfHoles = DEFAULT_NUMBER_OF_HOLEP_HOLES; @@ -168,6 +170,24 @@ public PeerBuilderNAT bufferSize(Integer bufferSize) { this.bufferSize = bufferSize; return this; } + + public Integer heartBeatMillis() { + return heartBeatMillis; + } + + public PeerBuilderNAT heartBeatMillis(Integer heartBeatMillis) { + this.heartBeatMillis = heartBeatMillis; + return this; + } + + public Integer idleTCP() { + return idleTCP; + } + + public PeerBuilderNAT idleTCP(Integer idleTCP) { + this.idleTCP = idleTCP; + return this; + } public PeerNAT start() { @@ -195,6 +215,15 @@ public PeerNAT start() { bufferSize = 16; } + if(heartBeatMillis == null) { + heartBeatMillis = 2000; + } + + if(idleTCP == null) { + idleTCP = 5000; + } + + final NATUtils natUtils = new NATUtils(); final RconRPC rconRPC = new RconRPC(peer); final HolePRPC holePunchRPC = new HolePRPC(peer); @@ -203,7 +232,7 @@ public PeerNAT start() { peer.peerBean().holePNumberOfHoles(holePNumberOfHoles); peer.peerBean().holePNumberOfPunches(holePNumberOfPunches); - final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC, bufferTimeoutSeconds, bufferSize); + final RelayRPC relayRPC = new RelayRPC(peer, rconRPC, holePunchRPC, bufferTimeoutSeconds, bufferSize, heartBeatMillis, idleTCP); if(executorService == null) { executorService = Executors.newSingleThreadExecutor(); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index a376be220..ae6a0bac4 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -84,8 +84,10 @@ public class RelayRPC extends DispatchHandler { final private int bufferTimeoutSeconds; final private int bufferSize; + final private int heartBeatMillis; + final private int idleTCP; - public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, int bufferTimeoutSeconds, int bufferSize) { + public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, int bufferTimeoutSeconds, int bufferSize, int heartBeatMillis, int idleTCP) { super(peer.peerBean(), peer.connectionBean()); this.peer = peer; //this.servers = new ConcurrentHashMap(); @@ -94,6 +96,8 @@ public RelayRPC(Peer peer, RconRPC rconRPC, HolePRPC holePRPC, int bufferTimeout this.holePunchRPC = holePRPC; this.bufferTimeoutSeconds = bufferTimeoutSeconds; this.bufferSize = bufferSize; + this.heartBeatMillis = heartBeatMillis; + this.idleTCP = idleTCP; // register this handler register(RPC.Commands.RELAY.getNr()); @@ -108,7 +112,7 @@ public FutureDone sendSetupMessage(final PeerAddress candidate) message.keepAlive(true); LOG.debug("Setting up relay connection to peer {}, message {}", candidate, message); - final FuturePeerConnection fpc = peer.createPeerConnection(candidate); + final FuturePeerConnection fpc = peer.createPeerConnection(candidate, heartBeatMillis, idleTCP); fpc.addListener(new BaseFutureAdapter() { public void operationComplete(final FuturePeerConnection futurePeerConnection) throws Exception { if (futurePeerConnection.isSuccess()) { From 189721756e4d2c040e64074f4a951c258b137ef9 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 16:16:05 +0200 Subject: [PATCH 105/135] fixed serialization --- .../src/main/java/net/tomp2p/storage/DataSerializer.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java index 2e7c66a8d..4e97bc58e 100644 --- a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java +++ b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java @@ -151,9 +151,12 @@ private Data deserializeMapDB(DataInput in) throws IOException { if(!retVal) { throw new IOException("data could not be read"); } - me = new byte[signatureFactory.signatureSize()]; - in.readFully(me); - buf = Unpooled.wrappedBuffer(me); + if(data.isSigned()) { + me = new byte[signatureFactory.signatureSize()]; + System.err.println("size: "+me.length); + in.readFully(me); + buf = Unpooled.wrappedBuffer(me); + } retVal = data.decodeDone(buf, signatureFactory); if(!retVal) { throw new IOException("signature could not be read"); From 352db811f566a712967ec3a1803ec04f29a014d7 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 16:16:51 +0200 Subject: [PATCH 106/135] remove printout --- storage/src/main/java/net/tomp2p/storage/DataSerializer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java index 4e97bc58e..66bf1dead 100644 --- a/storage/src/main/java/net/tomp2p/storage/DataSerializer.java +++ b/storage/src/main/java/net/tomp2p/storage/DataSerializer.java @@ -153,7 +153,6 @@ private Data deserializeMapDB(DataInput in) throws IOException { } if(data.isSigned()) { me = new byte[signatureFactory.signatureSize()]; - System.err.println("size: "+me.length); in.readFully(me); buf = Unpooled.wrappedBuffer(me); } From dce77112e031c186d57e876ee6046b971438f78c Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 16:53:50 +0200 Subject: [PATCH 107/135] fix tracker --- tracker/src/test/java/net/tomp2p/tracker/TestTracker.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java index 21e10d6dc..330df489a 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTracker.java @@ -379,9 +379,10 @@ public void testTrackerResponsibility() throws Exception { nodes[i].peer().peerBean().peerMap().peerFound(nodes[j].peerAddress(), null, null, null); } } + FutureTracker ft = nodes[30].getTracker(trackerID).start(); ft.awaitUninterruptibly(); - Assert.assertEquals(3, ft.trackers().size()); + Assert.assertEquals(2, ft.trackerPeers().size()); } finally { if (master != null) { master.peer().shutdown().await(); From ea60bf11997f9b4b64fd3f89905edfdb0ebda384 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 15 Oct 2015 18:39:04 +0200 Subject: [PATCH 108/135] Override fromAddress --- .../ChannelClientConfiguration.java | 20 +++++-------------- .../net/tomp2p/connection/Reservation.java | 9 +++++++-- .../main/java/net/tomp2p/p2p/PeerBuilder.java | 8 ++------ .../tomp2p/holep/manual/LocalNATUtils.java | 11 ++-------- 4 files changed, 16 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelClientConfiguration.java b/core/src/main/java/net/tomp2p/connection/ChannelClientConfiguration.java index 257d6ce15..bd44b45df 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelClientConfiguration.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelClientConfiguration.java @@ -40,8 +40,7 @@ public class ChannelClientConfiguration { private SignatureFactory signatureFactory; private Bindings bindings; - private InetAddress senderUDP; - private InetAddress senderTCP; + private InetAddress fromAddress = null; private boolean enablePool = false; private boolean enableHeap = false; @@ -148,21 +147,12 @@ public ChannelClientConfiguration bindings(Bindings bindings) { return this; } - public InetAddress senderUDP() { - return senderUDP; + public InetAddress fromAddress() { + return fromAddress; } - public ChannelClientConfiguration senderUDP(InetAddress senderUDP) { - this.senderUDP = senderUDP; - return this; - } - - public InetAddress senderTCP() { - return senderTCP; - } - - public ChannelClientConfiguration senderTCP(InetAddress senderUDP) { - this.senderTCP = senderUDP; + public ChannelClientConfiguration fromAddress(InetAddress fromAddress) { + this.fromAddress = fromAddress; return this; } diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index c54ab34d4..0a4af9e8f 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -374,7 +374,10 @@ public void run() { } final InetAddress fromAddress; - if(peerBean.serverPeerAddress() == null) { + + if(channelClientConfiguration.fromAddress() != null) { + fromAddress = channelClientConfiguration.fromAddress(); + } else if(peerBean.serverPeerAddress() == null) { fromAddress = Inet4Address.getByAddress(new byte[4]); } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); @@ -454,7 +457,9 @@ public void run() { } final InetAddress fromAddress; - if(peerBean.serverPeerAddress() == null) { + if(channelClientConfiguration.fromAddress() != null) { + fromAddress = channelClientConfiguration.fromAddress(); + } else if(peerBean.serverPeerAddress() == null) { fromAddress = Inet4Address.getByAddress(new byte[4]); } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index 9f686bfe7..cb86eb5f8 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -16,11 +16,7 @@ package net.tomp2p.p2p; -import io.netty.channel.ChannelHandler; -import io.netty.util.concurrent.EventExecutorGroup; - import java.io.IOException; -import java.net.InetSocketAddress; import java.security.KeyPair; import java.security.PublicKey; import java.util.ArrayList; @@ -30,6 +26,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import io.netty.channel.ChannelHandler; +import io.netty.util.concurrent.EventExecutorGroup; import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.connection.ChannelServerConfiguration; @@ -344,8 +342,6 @@ public static ChannelClientConfiguration createDefaultChannelClientConfiguration channelClientConfiguration.maxPermitsUDP(MAX_PERMITS_UDP); channelClientConfiguration.pipelineFilter(new DefaultPipelineFilter()); channelClientConfiguration.signatureFactory(new DSASignatureFactory()); - channelClientConfiguration.senderTCP(new InetSocketAddress(0).getAddress()); - channelClientConfiguration.senderUDP(new InetSocketAddress(0).getAddress()); channelClientConfiguration.byteBufPool(false); return channelClientConfiguration; } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index 9f57f5496..fb2467140 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -17,7 +17,6 @@ import java.util.concurrent.atomic.AtomicReferenceArray; import net.tomp2p.connection.Bindings; -import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; import net.tomp2p.peers.Number160; @@ -280,9 +279,7 @@ public static Peer init(String ip, int port, int peerId) throws UnknownHostException, IOException { Bindings b = new Bindings(); b.addAddress(InetAddress.getByName(ip)); - ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); - ccc.senderTCP(InetAddress.getByName(ip)); - Peer peer = new PeerBuilder(Number160.createHash(peerId)).channelClientConfiguration(ccc).ports(port).bindings(b).behindFirewall().start(); + Peer peer = new PeerBuilder(Number160.createHash(peerId)).ports(port).bindings(b).behindFirewall().start(); System.out.println("Init "+peer.peerAddress()); return peer; } @@ -291,11 +288,7 @@ public static Peer init(String ip, int port, int peerId, int forwardedPort) throws UnknownHostException, IOException { Bindings b = new Bindings(); b.addAddress(InetAddress.getByName(ip)); - - ChannelClientConfiguration ccc = PeerBuilder.createDefaultChannelClientConfiguration(); - - ccc.senderTCP(InetAddress.getByName(ip)); - Peer peer = new PeerBuilder(Number160.createHash(peerId)).portsExternal(forwardedPort).channelClientConfiguration(ccc).ports(port).bindings(b) + Peer peer = new PeerBuilder(Number160.createHash(peerId)).portsExternal(forwardedPort).ports(port).bindings(b) .start(); System.out.println("Init "+peer.peerAddress()); return peer; From f4e3fee798259cb007676bf50ab8f3495c0a0174 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 22 Oct 2015 11:30:00 +0200 Subject: [PATCH 109/135] fixed 115 --- .../main/java/net/tomp2p/peers/PeerMap.java | 4 +- .../tomp2p/examples/ExampleReconnect2.java | 84 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 examples/src/main/java/net/tomp2p/examples/ExampleReconnect2.java diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index 19bfcbcf1..2b10269be 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -324,7 +324,9 @@ public boolean peerFound(PeerAddress remotePeer, final PeerAddress referrer, fin shutdownMap.containsKey(remotePeer.peerId()) || exceptionMap.containsKey(remotePeer.peerId()); - if((secondHand || thirdHand) && probablyDead) { + // don't include secondHand as if we are contacted by an assumed offline + // peer and we see the peer is there, assume the peer is not dead. + if(thirdHand && probablyDead) { LOG.debug("Most likely offline, reject"); return false; } diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleReconnect2.java b/examples/src/main/java/net/tomp2p/examples/ExampleReconnect2.java new file mode 100644 index 000000000..d4b9c7a97 --- /dev/null +++ b/examples/src/main/java/net/tomp2p/examples/ExampleReconnect2.java @@ -0,0 +1,84 @@ +package net.tomp2p.examples; + +import java.io.IOException; + +import net.tomp2p.futures.BaseFuture; +import net.tomp2p.futures.FutureDone; +import net.tomp2p.p2p.Peer; +import net.tomp2p.p2p.PeerBuilder; +import net.tomp2p.peers.Number160; + +public class ExampleReconnect2 { + public static void main(String[] args) throws IOException, InterruptedException { + Peer A = null; + Peer B = null; + Peer C = null; + Peer D = null; + Peer E = null; + try { + A = new PeerBuilder(new Number160(1)).ports(7000).start(); + B = new PeerBuilder(new Number160(2)).ports(7001).start(); + C = new PeerBuilder(new Number160(3)).ports(7002).start(); + D = new PeerBuilder(new Number160(4)).ports(7003).start(); + E = new PeerBuilder(new Number160(5)).ports(7004).start(); + + BaseFuture fb1 = B.bootstrap().peerAddress(A.peerAddress()).start().awaitUninterruptibly(); + System.out.println(fb1.isSuccess() + "/" +fb1.failedReason()); + + BaseFuture fb2 = C.bootstrap().peerAddress(B.peerAddress()).start().awaitUninterruptibly(); + System.out.println(fb2.isSuccess() + "/" +fb2.failedReason()); + + BaseFuture fb3 = D.bootstrap().peerAddress(C.peerAddress()).start().awaitUninterruptibly(); + System.out.println(fb3.isSuccess() + "/" +fb3.failedReason()); + + Thread.sleep(5000); + System.out.println("A sees: " + A.peerBean().peerMap().all()); + System.out.println("B sees: " + B.peerBean().peerMap().all()); + System.out.println("C sees: " + C.peerBean().peerMap().all()); + System.out.println("D sees: " + D.peerBean().peerMap().all()); + + //B goes offline + FutureDone fd = B.announceShutdown().start().awaitUninterruptibly(); + B.shutdown().awaitUninterruptibly(); + Thread.sleep(5000); + //comes online, bootstraps to C + B = new PeerBuilder(new Number160(2)).ports(7001).start(); + BaseFuture fb4 = B.bootstrap().peerAddress(C.peerAddress()).start().awaitUninterruptibly(); + System.out.println(fb4.isSuccess() + "/" +fb4.failedReason()); + Thread.sleep(5000); + + System.out.println("A sees: " + A.peerBean().peerMap().all()); + System.out.println("B sees: " + B.peerBean().peerMap().all()); + System.out.println("C sees: " + C.peerBean().peerMap().all()); + System.out.println("D sees: " + D.peerBean().peerMap().all()); + + //E boostraps to B + BaseFuture fb5 = E.bootstrap().peerAddress(B.peerAddress()).start().awaitUninterruptibly(); + System.out.println(fb5.isSuccess() + "/" +fb5.failedReason()); + + Thread.sleep(5000); + System.out.println("A sees: " + A.peerBean().peerMap().all()); + System.out.println("B sees: " + B.peerBean().peerMap().all()); + System.out.println("C sees: " + C.peerBean().peerMap().all()); + System.out.println("D sees: " + D.peerBean().peerMap().all()); + System.out.println("E sees: " + E.peerBean().peerMap().all()); + + } finally { + if(A != null) { + A.shutdown().awaitUninterruptibly(); + } + if(B != null) { + B.shutdown().awaitUninterruptibly(); + } + if(C != null) { + C.shutdown().awaitUninterruptibly(); + } + if(D != null) { + D.shutdown().awaitUninterruptibly(); + } + if(E != null) { + E.shutdown().awaitUninterruptibly(); + } + } + } +} From 19d32b2fb135b49049d8b6fe79a2fed4b5237523 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Thu, 29 Oct 2015 18:59:57 +0100 Subject: [PATCH 110/135] UDT and IPv6 improvments --- .../net/tomp2p/connection/ChannelCreator.java | 4 +- .../connection/DefaultSendBehavior.java | 6 +- .../net/tomp2p/connection/Dispatcher.java | 2 +- .../net/tomp2p/connection/PeerCreator.java | 46 +- .../java/net/tomp2p/connection/Ports.java | 29 +- .../net/tomp2p/connection/RequestHandler.java | 5 +- .../net/tomp2p/connection/Reservation.java | 12 +- .../java/net/tomp2p/connection/Sender.java | 58 +- .../net/tomp2p/connection/TimeoutFactory.java | 9 +- .../net/tomp2p/futures/FutureDiscover.java | 12 +- .../net/tomp2p/message/DSASignatureCodec.java | 4 +- .../main/java/net/tomp2p/message/Decoder.java | 103 +- .../main/java/net/tomp2p/message/Encoder.java | 166 +-- .../main/java/net/tomp2p/message/Message.java | 76 +- .../tomp2p/message/MessageHeaderCodec.java | 102 +- .../net/tomp2p/message/TomP2POutbound.java | 19 +- .../main/java/net/tomp2p/p2p/PeerBuilder.java | 8 +- .../java/net/tomp2p/p2p/SlowPeerFilter.java | 4 +- .../tomp2p/p2p/builder/BootstrapBuilder.java | 17 +- .../tomp2p/p2p/builder/DiscoverBuilder.java | 44 +- .../net/tomp2p/p2p/builder/PingBuilder.java | 19 +- core/src/main/java/net/tomp2p/peers/IP.java | 66 +- .../main/java/net/tomp2p/peers/Number160.java | 21 + .../java/net/tomp2p/peers/PeerAddress.java | 1182 ++++++----------- .../java/net/tomp2p/peers/PeerIPFilter.java | 46 +- .../main/java/net/tomp2p/peers/PeerMap.java | 12 +- .../net/tomp2p/peers/PeerSocketAddress.java | 577 ++++---- .../java/net/tomp2p/rpc/DispatchHandler.java | 2 +- .../src/main/java/net/tomp2p/rpc/PingRPC.java | 9 +- .../net/tomp2p/rpc/SimpleBloomFilter.java | 2 +- .../src/main/java/net/tomp2p/utils/Utils.java | 108 +- core/src/test/java/net/tomp2p/Utils2.java | 74 +- .../java/net/tomp2p/message/TestMessage.java | 125 +- .../test/java/net/tomp2p/peers/TestIP.java | 2 - .../net/tomp2p/peers/TestPeerAddress.java | 186 +-- .../test/java/net/tomp2p/dht/UtilsDHT2.java | 4 +- .../holep/strategy/AbstractHolePStrategy.java | 4 +- .../net/tomp2p/relay/DistributedRelay.java | 8 +- .../main/java/net/tomp2p/relay/Forwarder.java | 10 +- .../main/java/net/tomp2p/relay/RelayRPC.java | 12 +- .../holep/manual/TestNATForwarding.java | 6 +- .../holep/manual/TestNATHolePunching.java | 148 +++ .../net/tomp2p/holep/manual/TestNATLocal.java | 6 +- .../net/tomp2p/holep/manual/TestNATRelay.java | 32 +- .../tomp2p/holep/manual/TestNATStress.java | 6 +- .../net/tomp2p/holep/manual/TestUPNP.java | 4 +- .../java/net/tomp2p/relay/TestRelayUtils.java | 10 +- .../test/java/net/tomp2p/relay/UtilsNAT.java | 4 +- pom.xml | 27 +- .../src/test/java/net/tomp2p/Utils2.java | 4 +- 50 files changed, 1770 insertions(+), 1672 deletions(-) create mode 100644 nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java diff --git a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java index 92f8db86f..9251017e5 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java @@ -165,7 +165,7 @@ public ChannelFuture createUDP(final boolean broadcast, final Map 0) { + if (message.sender().relaySize() > 0) { // reverse connection is not possible because both peers are // relayed. Thus send the message to // one of the receiver's relay peers @@ -65,7 +65,7 @@ public SendMethod udpSendBehavior(Dispatcher dispatcher, Message message) throws return SendMethod.DIRECT; } - if(message.recipient().isRelayed()) { + if(message.recipient().relaySize() > 0) { return SendMethod.RELAY; } diff --git a/core/src/main/java/net/tomp2p/connection/Dispatcher.java b/core/src/main/java/net/tomp2p/connection/Dispatcher.java index 35fe3ac04..89bb9086f 100644 --- a/core/src/main/java/net/tomp2p/connection/Dispatcher.java +++ b/core/src/main/java/net/tomp2p/connection/Dispatcher.java @@ -180,7 +180,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message messa return; } - if(message.sender().isSlow() && message.isKeepAlive()) { + if(message.sender().slow() && message.isKeepAlive()) { //reset timer TimeoutFactory.resetTimeout(ctx, csc.idleTCPSlowMillis()); } diff --git a/core/src/main/java/net/tomp2p/connection/PeerCreator.java b/core/src/main/java/net/tomp2p/connection/PeerCreator.java index e5d8d3d9f..88eff8695 100644 --- a/core/src/main/java/net/tomp2p/connection/PeerCreator.java +++ b/core/src/main/java/net/tomp2p/connection/PeerCreator.java @@ -16,26 +16,26 @@ package net.tomp2p.connection; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.util.concurrent.DefaultThreadFactory; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; - import java.io.IOException; import java.net.InetAddress; import java.security.KeyPair; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.util.concurrent.DefaultThreadFactory; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureDone; +import net.tomp2p.peers.IP.IPv4; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; /** * Creates a peer and listens to incoming connections. The result of creating @@ -121,7 +121,7 @@ public PeerCreator(final PeerCreator parent, final Number160 peerId, final KeyPa this.bossGroup = parent.bossGroup; this.connectionBean = parent.connectionBean; this.peerBean = new PeerBean(keyPair); - PeerAddress self = parent.peerBean().serverPeerAddress().changePeerId(peerId); + PeerAddress self = parent.peerBean().serverPeerAddress().withPeerId(peerId); this.peerBean.serverPeerAddress(self); this.master = false; } @@ -223,11 +223,25 @@ private static PeerAddress findPeerAddress(final Number160 peerId, if(outsideAddress == null) { throw new IOException("Not listening to anything. Maybe the binding information is wrong."); } - final PeerSocketAddress peerSocketAddress = new PeerSocketAddress(outsideAddress, channelServerConfiguration. - ports().tcpPort(), channelServerConfiguration.ports().udpPort()); - final PeerAddress self = new PeerAddress(peerId, peerSocketAddress, null, - channelServerConfiguration.isBehindFirewall(), channelServerConfiguration.isBehindFirewall(), false, false, false, false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); + + final PeerSocket4Address peerSocketAddress = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(outsideAddress)) + .tcpPort(channelServerConfiguration.ports().tcpPort()) + .udpPort(channelServerConfiguration.ports().udpPort()) + + .build(); + + final PeerAddress self = PeerAddress.builder() + .peerId(peerId) + .ipv4Socket(peerSocketAddress) + .reachable4UDP(!channelServerConfiguration.isBehindFirewall()) + .reachable4TCP(!channelServerConfiguration.isBehindFirewall()) + .reachable4UDT(!channelServerConfiguration.isBehindFirewall()) + .reachable6UDP(!channelServerConfiguration.isBehindFirewall()) + .reachable6TCP(!channelServerConfiguration.isBehindFirewall()) + .reachable6UDT(!channelServerConfiguration.isBehindFirewall()) + .unreachable(channelServerConfiguration.isBehindFirewall()) + .build(); + return self; } } diff --git a/core/src/main/java/net/tomp2p/connection/Ports.java b/core/src/main/java/net/tomp2p/connection/Ports.java index f350cc65d..b795d485e 100644 --- a/core/src/main/java/net/tomp2p/connection/Ports.java +++ b/core/src/main/java/net/tomp2p/connection/Ports.java @@ -38,13 +38,17 @@ public class Ports { // i.e., manual port-forwarding private final int tcpPort; private final int udpPort; + private final int udtPort; private final boolean randomPorts; /** * Creates random ports for TCP and UDP. The random ports start from port 49152 */ public Ports() { - this(-1, -1); + this.tcpPort = RND.nextInt(RANGE) + MIN_DYN_PORT; + this.udpPort = RND.nextInt(RANGE) + MIN_DYN_PORT; + this.udtPort = RND.nextInt(RANGE) + MIN_DYN_PORT; + this.randomPorts = true; } /** @@ -52,10 +56,14 @@ public Ports() { * @param tcpPort The external TCP port, how other peers will see us. If the provided port is < 0, a random port will be used. * @param udpPort The external UDP port, how other peers will see us. If the provided port is < 0, a random port will be used. */ - public Ports(final int tcpPort, final int udpPort) { - this.randomPorts = tcpPort < 0 && udpPort < 0; - this.tcpPort = tcpPort < 0 ? (RND.nextInt(RANGE) + MIN_DYN_PORT) : tcpPort; - this.udpPort = udpPort < 0 ? (RND.nextInt(RANGE) + MIN_DYN_PORT) : udpPort; + public Ports(final int tcpPort, final int udpPort, final int udtPort) { + if(tcpPort < 1 || udpPort < 1 || udtPort < 1) { + throw new IllegalArgumentException("manual ports need to be > 1"); + } + this.tcpPort = tcpPort; + this.udpPort = udpPort; + this.udtPort = udtPort; + this.randomPorts = false; } /** @@ -71,6 +79,13 @@ public int tcpPort() { public int udpPort() { return udpPort; } + + /** + * @return The external UDP port, how other peers see us. + */ + public int udtPort() { + return udtPort; + } /** * @return True, if the user specified both ports in advance. This tells us @@ -86,8 +101,8 @@ public boolean isManualPort() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("ports(u"); - sb.append(udpPort).append(",t").append(tcpPort).append(")"); + final StringBuilder sb = new StringBuilder("ports(udp:"); + sb.append(udpPort).append(",tcp:").append(tcpPort).append(",udt:").append(udtPort).append(")"); return sb.toString(); } } diff --git a/core/src/main/java/net/tomp2p/connection/RequestHandler.java b/core/src/main/java/net/tomp2p/connection/RequestHandler.java index a97b8cd7e..93afb13b4 100644 --- a/core/src/main/java/net/tomp2p/connection/RequestHandler.java +++ b/core/src/main/java/net/tomp2p/connection/RequestHandler.java @@ -24,7 +24,6 @@ import net.tomp2p.message.Message; import net.tomp2p.message.MessageID; import net.tomp2p.peers.PeerStatusListener; -import net.tomp2p.rpc.RPC; /** * Is able to send TCP and UDP messages (as a request) and processes incoming responses. It is important that @@ -294,7 +293,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo //NAT reflection, change it back, as this will be stored in our peer map that may be queried from other peers if(message.recipientReflected() != null) { - responseMessage.sender(message.recipient().changePeerSocketAddress(message.recipient().peerSocketAddress())); + responseMessage.sender(message.recipient().withIpv4Socket(message.recipient().ipv4Socket())); } // Stop time measurement of RTT @@ -314,7 +313,7 @@ protected void channelRead0(final ChannelHandlerContext ctx, final Message respo } // support slow, unreachable devices which cannot respond instantly - if(this.message.recipient().isRelayed() && this.message.recipient().isSlow() && responseMessage.type() == Message.Type.PARTIALLY_OK) { + if(this.message.recipient().relaySize() > 0 && this.message.recipient().slow() && responseMessage.type() == Message.Type.PARTIALLY_OK) { LOG.debug("Received partially ok by the relay peer. Wait for answer of the unreachable peer."); // wait for the (real) answer of the unreachable peer. connectionBean.dispatcher().addPendingRequest(message.messageId(), futureResponse, slowResponseTimeoutSeconds, connectionBean.timer()); diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 0a4af9e8f..00d3afa98 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -379,10 +379,10 @@ public void run() { fromAddress = channelClientConfiguration.fromAddress(); } else if(peerBean.serverPeerAddress() == null) { fromAddress = Inet4Address.getByAddress(new byte[4]); - } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { - fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); + } else if(peerBean.serverPeerAddress().net4Internal()) { + fromAddress = peerBean.serverPeerAddress().ipInternalSocket().ipv4().toInetAddress(); } else { - fromAddress = peerBean.serverPeerAddress().inetAddress(); + fromAddress = peerBean.serverPeerAddress().ipv4Socket().ipv4().toInetAddress(); } LOG.debug("channel from {}", fromAddress); @@ -461,10 +461,10 @@ public void run() { fromAddress = channelClientConfiguration.fromAddress(); } else if(peerBean.serverPeerAddress() == null) { fromAddress = Inet4Address.getByAddress(new byte[4]); - } else if(peerBean.serverPeerAddress().internalPeerSocketAddress() != null) { - fromAddress = peerBean.serverPeerAddress().internalPeerSocketAddress().inetAddress(); + } else if(peerBean.serverPeerAddress().net4Internal()) { + fromAddress = peerBean.serverPeerAddress().ipInternalSocket().ipv4().toInetAddress(); } else { - fromAddress = peerBean.serverPeerAddress().inetAddress(); + fromAddress = peerBean.serverPeerAddress().ipInternalSocket().ipv4().toInetAddress(); } LOG.debug("channel from {}", fromAddress); diff --git a/core/src/main/java/net/tomp2p/connection/Sender.java b/core/src/main/java/net/tomp2p/connection/Sender.java index e02123773..af82e5439 100644 --- a/core/src/main/java/net/tomp2p/connection/Sender.java +++ b/core/src/main/java/net/tomp2p/connection/Sender.java @@ -51,6 +51,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.peers.PeerStatusListener; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; @@ -199,12 +200,12 @@ private void handleRcon(final SimpleChannelInboundHandler handler, fina final TimeoutFactory timeoutHandler) { message.keepAlive(true); - PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().ipInternalSocket()); if(ps == null) { futureResponse.failed("no relay provided, but relay indicated RCON"); return; } - if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + if(ps.equals(peerBean.serverPeerAddress().ipv4Socket())) { LOG.debug("Send to self-relay RCON"); sendSelf(futureResponse, message); return; @@ -279,8 +280,20 @@ private static Message createRconMessage(PeerSocketAddress ps, final Message mes */ private static void readyToSend(final Message originalMessage, PeerSocketAddress socketAddress, Message newMessage, byte RPCCommand, Type messageType) { - PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) - .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); + PeerSocket4Address psa = originalMessage.recipient().ipv4Socket(); + + if(socketAddress instanceof PeerSocket4Address) { + PeerSocket4Address socketAddress4 = (PeerSocket4Address) socketAddress; + + psa = psa.withIpv4(socketAddress4.ipv4()) + .withTcpPort(socketAddress4.tcpPort()) + .withUdpPort(socketAddress4.udpPort()); + + } + + PeerAddress recipient = originalMessage.recipient().withIpv4Socket(psa) + .withRelaySize(0); + newMessage.recipient(recipient); newMessage.command(RPCCommand); @@ -304,9 +317,9 @@ private void connectAndSend(final SimpleChannelInboundHandler handler, final TimeoutFactory timeoutHandler, final Message message) { final InetSocketAddress recipient; if(message.recipientReflected() != null) { - recipient = message.recipientReflected().createSocketTCP(); + recipient = message.recipientReflected().ipv4Socket().createTCPSocket(); } else { - recipient = message.recipient().createSocketTCP(); + recipient = message.recipient().ipv4Socket().createTCPSocket(); } final ChannelFuture channelFuture = sendTCPCreateChannel(recipient, channelCreator, peerConnection, handler, timeoutHandler, @@ -331,17 +344,17 @@ private void handleRelay(final SimpleChannelInboundHandler handler, fin final Message message, final ChannelCreator channelCreator, final int idleTCPMillis, final int connectTimeoutMillis, final PeerConnection peerConnection, final TimeoutFactory timeoutHandler) { - PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().ipv4Socket()); if(ps == null) { futureResponse.failed("no relay provided, but relay indicated TCP"); return; } - if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + if(ps.equals(peerBean.serverPeerAddress().ipv4Socket())) { LOG.debug("Send to self-relay TCP"); sendSelf(futureResponse, message); return; } - InetSocketAddress recipient = PeerSocketAddress.createSocketTCP(ps); + InetSocketAddress recipient = ps.createTCPSocket(); ChannelFuture channelFuture = sendTCPCreateChannel(recipient, channelCreator, peerConnection, handler, timeoutHandler, connectTimeoutMillis, futureResponse); afterConnect(futureResponse, message, channelFuture, handler == null); } @@ -557,12 +570,12 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu } break; case RELAY: - PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().ipv4Socket()); if(ps == null) { futureResponse.failed("no relay provided, but relay indicated UDP"); return; } - if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + if(ps.equals(peerBean.serverPeerAddress().ipv4Socket())) { LOG.debug("Send to self-relay UDP, {}", message); sendSelf(futureResponse, message); return; @@ -585,9 +598,9 @@ public void sendUDP(final SimpleChannelInboundHandler handler, final Fu } private void handleReflection(final Message message) { - PeerSocketAddress reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); + PeerSocket4Address reflectedRecipient = Utils.natReflection(message.recipient(), dispatcher.peerBean().serverPeerAddress()); if(reflectedRecipient != null) { - message.recipientReflected(message.recipient().changePeerSocketAddress(reflectedRecipient)); + message.recipientReflected(message.recipient().withIpv4Socket(reflectedRecipient)); LOG.debug("reflect recipient UDP {}", message); } } @@ -605,23 +618,18 @@ private void handleReflection(final Message message) { * @return * @throws Exception */ - private PeerSocketAddress prepareRelaySend(final Message message, final PeerSocketAddress preferredAddress) { - List psa = new ArrayList(message.recipient().peerSocketAddresses()); + private PeerSocketAddress prepareRelaySend(final Message message, final PeerSocket4Address preferredAddress) { + List psa = new ArrayList(message.recipient().relays()); if (psa.size() > 0) { if(psa.contains(preferredAddress)) { LOG.debug("send neighbor request to preferred relay peer {} out of {}", preferredAddress, psa); return preferredAddress; } - //check for any reflected addresses. Those are *not* preferred. Although they may be more efficient, - //we don't have any internal address information in peersocketaddress -> TODO while(!psa.isEmpty()) { PeerSocketAddress ps = psa.remove(random.nextInt(psa.size())); - if(peerBean.serverPeerAddress().isPortForwarding() && - ps.inetAddress().equals(peerBean.serverPeerAddress().peerSocketAddress().inetAddress())) { - continue; - } - message.recipientRelay(message.recipient().changePeerSocketAddress(ps).changeRelayed(true)); + //TODO: prefer local ones + message.recipientRelay(message.recipient().withIPSocket(ps)); LOG.debug("send neighbor request to random relay peer {} out of {}", ps, psa); return ps; } @@ -665,12 +673,12 @@ public void exceptionCaught(Throwable t) throws Exception { private void doRelayFallback(final FutureResponse futureResponse, final Message message, final boolean broadcast, final Map> handlers, ChannelFuture channelFuture) { - PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().peerSocketAddress()); + PeerSocketAddress ps = prepareRelaySend(message, peerBean.serverPeerAddress().ipv4Socket()); if(ps == null) { futureResponse.failed("no relay provided, but relay indicated HP"); return; } - if(ps.equals(peerBean.serverPeerAddress().peerSocketAddress())) { + if(ps.equals(peerBean.serverPeerAddress().ipv4Socket())) { LOG.debug("Send to self-relay HP"); sendSelf(futureResponse, message); return; @@ -846,7 +854,7 @@ private void removePeerIfFailed(final FutureResponse futureResponse, final Messa @Override public void operationComplete(FutureResponse future) throws Exception { if (future.isFailed()) { - if (message.recipient().isRelayed()) { + if (message.recipient().relaySize() > 0) { // TODO: make the relay go away if failed } else if (message.command() == RPC.Commands.HOLEP.getNr() && message.type().ordinal() == Message.Type.REQUEST_3.ordinal()) { //do nothing, because such a (dummy) message will never reach its target the first time diff --git a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java index 80916987d..8bef52f06 100644 --- a/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java +++ b/core/src/main/java/net/tomp2p/connection/TimeoutFactory.java @@ -31,7 +31,9 @@ import net.tomp2p.message.Decoder; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.peers.PeerStatusListener; +import net.tomp2p.peers.IP.IPv4; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -148,6 +150,7 @@ public void operationComplete(final ChannelFuture future) throws Exception { recipient = futureResponse.request().recipient(); } else { + //null if its a connection on the server LOG.warn("Channel timeout for channel {} {}.", name, ctx.channel()); ctx.close(); // check if we have set an attribute at least (if we have @@ -171,9 +174,9 @@ public void operationComplete(final ChannelFuture future) throws Exception { inetSocketAddress = pa.get(); } if (inetSocketAddress != null) { - peerStatusListener.peerFailed( - new PeerAddress(Number160.ZERO, inetSocketAddress.getAddress()), - new PeerException(AbortCause.TIMEOUT, "Timeout!")); + PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inetSocketAddress.getAddress())).build(); + PeerAddress peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(Number160.ZERO).build(); + peerStatusListener.peerFailed(peerAddress, new PeerException(AbortCause.TIMEOUT, "Timeout!")); } else { LOG.warn("Cannot determine the sender's address!"); } diff --git a/core/src/main/java/net/tomp2p/futures/FutureDiscover.java b/core/src/main/java/net/tomp2p/futures/FutureDiscover.java index 3cc6e9cb8..4a082a04f 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDiscover.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDiscover.java @@ -16,12 +16,12 @@ package net.tomp2p.futures; -import java.net.InetAddress; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; /** * The future that keeps track of network discovery such as discovery if its behind a NAT, the status if UPNP or NAT-PMP @@ -42,9 +42,9 @@ public class FutureDiscover extends BaseFutureImpl { private boolean isNat = false; - private InetAddress internalAddress; + private PeerSocket4Address internalAddress; - private InetAddress externalAddress; + private PeerSocket4Address externalAddress; /** * Constructor. @@ -206,7 +206,7 @@ public FutureDiscover failed(PeerAddress serverPeerAddress, final String failed) return this; } - public FutureDiscover externalHost(String failed, InetAddress internalAddress, InetAddress externalAddress) { + public FutureDiscover externalHost(String failed, PeerSocket4Address internalAddress, PeerSocket4Address externalAddress) { synchronized (lock) { if (!completedAndNotify()) { return this; @@ -222,13 +222,13 @@ public FutureDiscover externalHost(String failed, InetAddress internalAddress, I } - public InetAddress internalAddress() { + public PeerSocket4Address internalAddress() { synchronized (lock) { return internalAddress; } } - public InetAddress externalAddress() { + public PeerSocket4Address externalAddress() { synchronized (lock) { return externalAddress; } diff --git a/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java b/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java index aba42c098..6222883a2 100644 --- a/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java +++ b/core/src/main/java/net/tomp2p/message/DSASignatureCodec.java @@ -103,10 +103,10 @@ public byte[] encode() { me[1] = 2 * (20 + 2); me[2] = 0x02; me[3] = 20; - number1.toByteArray(me, 4); + number1.encode(me, 4); me[24] = 0x02; me[25] = 20; - number2.toByteArray(me, 26); + number2.encode(me, 26); return me; } diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index 01db7d3b8..40eb1bbda 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -1,11 +1,5 @@ package net.tomp2p.message; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.socket.DatagramChannel; -import io.netty.util.Attribute; -import io.netty.util.AttributeKey; - import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.security.InvalidKeyException; @@ -20,11 +14,18 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; -import java.util.List; import java.util.Queue; import java.util.Set; import java.util.TreeMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramChannel; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; import net.tomp2p.connection.SignatureFactory; import net.tomp2p.connection.TimeoutFactory; import net.tomp2p.message.Message.Content; @@ -32,15 +33,13 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.rpc.SimpleBloomFilter; import net.tomp2p.storage.Data; import net.tomp2p.storage.DataBuffer; import net.tomp2p.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class Decoder { public static final AttributeKey INET_ADDRESS_KEY = AttributeKey.valueOf("inet-addr"); @@ -53,15 +52,12 @@ public class Decoder { // private Message2 result = null; // current state - needs to be deleted if we want to reuse - private Message message = null; + private final Message message = new Message(); private boolean headerDone = false; private Signature signature = null; private int neighborSize = -1; private NeighborSet neighborSet = null; - - private int peerSocketAddressSize = -1; - private List peerSocketAddresses = null; private int keyCollectionSize = -1; private KeyCollection keyCollection = null; @@ -104,7 +100,7 @@ public boolean decode(ChannelHandlerContext ctx, final ByteBuf buf, InetSocketAd final Attribute attributeInet = ctx.attr(INET_ADDRESS_KEY); attributeInet.set(sender); - if (message == null && !headerDone) { + if (!headerDone) { headerDone = decodeHeader(buf, recipient, sender); if (headerDone) { // store the sender as an attribute @@ -122,14 +118,6 @@ public boolean decode(ChannelHandlerContext ctx, final ByteBuf buf, InetSocketAd final boolean donePayload = decodePayload(buf); decodeSignature(buf, readerBefore, donePayload); - if(donePayload) { - boolean isRelay = message.sender().isRelayed(); - if(isRelay && !message.peerSocketAddresses().isEmpty()) { - PeerAddress tmpSender = message.sender().changePeerSocketAddresses(message.peerSocketAddresses()); - message.sender(tmpSender); - } - } - // see https://github.com/netty/netty/issues/1976 buf.discardSomeReadBytes(); return donePayload; @@ -182,23 +170,23 @@ private void verifySignature(final ByteBuf buf, final int readerBefore, final in public boolean decodeHeader(final ByteBuf buf, InetSocketAddress recipient, final InetSocketAddress sender) { if (message == null) { - if (buf.readableBytes() < MessageHeaderCodec.HEADER_SIZE) { + if (buf.readableBytes() < MessageHeaderCodec.HEADER_SIZE_MIN) { // we don't have the header yet, we need the full header first // wait for more data return false; } - message = MessageHeaderCodec.decodeHeader(buf, recipient, sender); + final int readerIndex = buf.readerIndex(); + final boolean success = MessageHeaderCodec.decodeHeader(buf, recipient, sender, message); + if(!success) { + buf.readerIndex(readerIndex); + return false; + } } - if (message.sender().isNet4Private() && buf.readableBytes() < MessageHeaderCodec.HEADER_PRIVATE_ADDRESS_SIZE) { - return false; - } else if (message.sender().isNet4Private() && buf.readableBytes() >= MessageHeaderCodec.HEADER_PRIVATE_ADDRESS_SIZE){ - PeerSocketAddress internalPeerSocketAddress = PeerSocketAddress.create(buf, true); - message.sender(message.sender().changeInternalPeerSocketAddress(internalPeerSocketAddress)); - } // we have set the content types already message.presetContentTypes(true); - for (Content content : message.contentTypes()) { + + for (Content content : message.contentTypes()) { if (content == Content.EMPTY) { break; } @@ -270,15 +258,14 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, neighborSet = new NeighborSet(-1, new ArrayList(neighborSize)); } for (int i = neighborSet.size(); i < neighborSize; i++) { - if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) { + if (buf.readableBytes() < 4) { return false; } - int header = buf.getUnsignedShort(buf.readerIndex()); - size = PeerAddress.size(header); + size = PeerAddress.size(buf.getInt(buf.readerIndex())); if (buf.readableBytes() < size) { return false; } - PeerAddress pa = new PeerAddress(buf); + PeerAddress pa = PeerAddress.decode(buf); neighborSet.add(pa); } message.neighborsSet(neighborSet); @@ -286,34 +273,19 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, neighborSize = -1; neighborSet = null; break; - case SET_PEER_SOCKET: - if (peerSocketAddressSize == -1 && buf.readableBytes() < Utils.BYTE_BYTE_SIZE) { + case PEER_SOCKET4: + if (buf.readableBytes() < PeerSocket4Address.SIZE) { return false; } - if (peerSocketAddressSize == -1) { - peerSocketAddressSize = buf.readUnsignedByte(); - } - if (peerSocketAddresses == null) { - peerSocketAddresses = new ArrayList(peerSocketAddressSize); - } - for (int i = peerSocketAddresses.size(); i < peerSocketAddressSize; i++) { - if (buf.readableBytes() < Utils.BYTE_BYTE_SIZE) { - return false; - } - int header = buf.getUnsignedByte(buf.readerIndex()); - boolean isIPv4 = header == 0; - size = PeerSocketAddress.size(isIPv4); - if (buf.readableBytes() < size + Utils.BYTE_BYTE_SIZE) { - return false; - } - //skip the ipv4/ipv6 header - buf.skipBytes(1); - peerSocketAddresses.add(PeerSocketAddress.create(buf, isIPv4)); + message.peerSocket4Address(PeerSocket4Address.decode(buf)); + lastContent = contentTypes.poll(); + break; + case PEER_SOCKET6: + if (buf.readableBytes() < PeerSocket6Address.SIZE) { + return false; } - message.peerSocketAddresses(peerSocketAddresses); + message.peerSocket6Address(PeerSocket6Address.decode(buf)); lastContent = contentTypes.poll(); - peerSocketAddressSize = -1; - peerSocketAddresses = null; break; case SET_KEY640: if (keyCollectionSize == -1 && buf.readableBytes() < Utils.INTEGER_BYTE_SIZE) { @@ -539,18 +511,16 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, } for (int i = trackerData.size(); i < trackerDataSize; i++) { - if (buf.readableBytes() < Utils.SHORT_BYTE_SIZE) { + if (buf.readableBytes() < 4) { return false; } - int header = buf.getUnsignedShort(buf.readerIndex()); - - size = PeerAddress.size(header); + size = PeerAddress.size(buf.getInt(buf.readerIndex())); if (buf.readableBytes() < size) { return false; } - PeerAddress pa = new PeerAddress(buf); + PeerAddress pa = PeerAddress.decode(buf); currentTrackerData = Data.decodeHeader(buf, signatureFactory); if (currentTrackerData == null) { @@ -611,7 +581,6 @@ public Message prepareFinish() { Message ret = message; message.setDone(); contentTypes.clear(); - message = null; headerDone = false; neighborSize = -1; neighborSet = null; diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index 78302dda8..fb3f44ef0 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -5,32 +5,30 @@ import java.security.PublicKey; import java.security.SignatureException; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.Map.Entry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.SignatureFactory; import net.tomp2p.message.Message.Content; import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.rpc.SimpleBloomFilter; import net.tomp2p.storage.AlternativeCompositeByteBuf; import net.tomp2p.storage.Data; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class Encoder { private static final Logger LOG = LoggerFactory.getLogger(Encoder.class); private final DataFilter dataFilterTTL = new DataFilterTTL(); - private boolean header = false; - private boolean resume = false; private Message message; private final SignatureFactory signatureFactory; @@ -39,23 +37,13 @@ public Encoder(SignatureFactory signatureFactory) { this.signatureFactory = signatureFactory; } - public boolean write(final AlternativeCompositeByteBuf buf, final Message message, SignatureCodec signatureCodec) throws InvalidKeyException, + public boolean write(final AlternativeCompositeByteBuf buf, final Message message, SignatureCodec signatureCodec, boolean ipv6) throws InvalidKeyException, SignatureException, IOException { this.message = message; LOG.debug("message for outbound {}", message); - - if (message.sender().isRelayed() && message.peerSocketAddresses().isEmpty()) { - message.peerSocketAddresses(message.sender().peerSocketAddresses()); - } - - if (!header) { - MessageHeaderCodec.encodeHeader(buf, message); - header = true; - } else { - LOG.debug("send a follow-up message {}", message); - resume = true; - } + + MessageHeaderCodec.encodeHeader(buf, message, ipv6); boolean done = loop(buf); LOG.debug("message encoded {}", message); @@ -83,7 +71,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException final Content content = next.content(); switch (content) { case KEY: - buf.writeBytes(message.key(next.index()).toByteArray()); + message.key(next.index()).encode(buf); message.contentReferences().poll(); break; case INTEGER: @@ -95,131 +83,117 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException message.contentReferences().poll(); break; case SET_NEIGHBORS: - NeighborSet neighborSet = message.neighborsSet(next.index()); + final NeighborSet neighborSet = message.neighborsSet(next.index()); // length buf.writeByte(neighborSet.size()); for (PeerAddress neighbor : neighborSet.neighbors()) { - buf.writeBytes(neighbor.toByteArray()); + neighbor.encode(buf); } message.contentReferences().poll(); break; - case SET_PEER_SOCKET: - List list = message.peerSocketAddresses(); - // length - buf.writeByte(list.size()); - for (PeerSocketAddress psa : list) { - // IP version flag - buf.writeByte(psa.isIPv4() ? 0:1); - buf.writeBytes(psa.toByteArray()); - } + case PEER_SOCKET4: + final PeerSocket4Address psa4 = message.peerSocket4Address(next.index()); + psa4.encode(buf); + message.contentReferences().poll(); + break; + case PEER_SOCKET6: + final PeerSocket6Address psa6 = message.peerSocket6Address(next.index()); + psa6.encode(buf); message.contentReferences().poll(); break; case BLOOM_FILTER: - SimpleBloomFilter simpleBloomFilter = message.bloomFilter(next.index()); - simpleBloomFilter.toByteBuf(buf); + final SimpleBloomFilter simpleBloomFilter = message.bloomFilter(next.index()); + simpleBloomFilter.encode(buf); message.contentReferences().poll(); break; case SET_KEY640: - KeyCollection keys = message.keyCollection(next.index()); + final KeyCollection keys = message.keyCollection(next.index()); // length buf.writeInt(keys.size()); if (keys.isConvert()) { - for (Number160 key : keys.keysConvert()) { - buf.writeBytes(keys.locationKey().toByteArray()); - buf.writeBytes(keys.domainKey().toByteArray()); - buf.writeBytes(key.toByteArray()); - buf.writeBytes(keys.versionKey().toByteArray()); + for (final Number160 key : keys.keysConvert()) { + keys.locationKey().encode(buf); + keys.domainKey().encode(buf); + key.encode(buf); + keys.versionKey().encode(buf); } } else { - for (Number640 key : keys.keys()) { - buf.writeBytes(key.locationKey().toByteArray()); - buf.writeBytes(key.domainKey().toByteArray()); - buf.writeBytes(key.contentKey().toByteArray()); - buf.writeBytes(key.versionKey().toByteArray()); + for (final Number640 key : keys.keys()) { + key.locationKey().encode(buf); + key.domainKey().encode(buf); + key.contentKey().encode(buf); + key.versionKey().encode(buf); } } message.contentReferences().poll(); break; case MAP_KEY640_DATA: - DataMap dataMap = message.dataMap(next.index()); + final DataMap dataMap = message.dataMap(next.index()); // length buf.writeInt(dataMap.size()); if (dataMap.isConvert()) { - for (Entry entry : dataMap.dataMapConvert().entrySet()) { - buf.writeBytes(dataMap.locationKey().toByteArray()); - buf.writeBytes(dataMap.domainKey().toByteArray()); - buf.writeBytes(entry.getKey().toByteArray()); - buf.writeBytes(dataMap.versionKey().toByteArray()); + for (final Entry entry : dataMap.dataMapConvert().entrySet()) { + dataMap.locationKey().encode(buf); + dataMap.domainKey().encode(buf); + entry.getKey().encode(buf); + dataMap.versionKey().encode(buf); encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } } else { - for (Entry entry : dataMap.dataMap().entrySet()) { - buf.writeBytes(entry.getKey().locationKey().toByteArray()); - buf.writeBytes(entry.getKey().domainKey().toByteArray()); - buf.writeBytes(entry.getKey().contentKey().toByteArray()); - buf.writeBytes(entry.getKey().versionKey().toByteArray()); + for (final Entry entry : dataMap.dataMap().entrySet()) { + entry.getKey().locationKey().encode(buf); + entry.getKey().domainKey().encode(buf); + entry.getKey().contentKey().encode(buf); + entry.getKey().versionKey().encode(buf); encodeData(buf, entry.getValue(), dataMap.isConvertMeta(), !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } } message.contentReferences().poll(); break; case MAP_KEY640_KEYS: - KeyMap640Keys keyMap640Keys = message.keyMap640Keys(next.index()); + final KeyMap640Keys keyMap640Keys = message.keyMap640Keys(next.index()); // length buf.writeInt(keyMap640Keys.size()); - for (Entry> entry : keyMap640Keys.keysMap().entrySet()) { - buf.writeBytes(entry.getKey().locationKey().toByteArray()); - buf.writeBytes(entry.getKey().domainKey().toByteArray()); - buf.writeBytes(entry.getKey().contentKey().toByteArray()); - buf.writeBytes(entry.getKey().versionKey().toByteArray()); + for (final Entry> entry : keyMap640Keys.keysMap().entrySet()) { + entry.getKey().locationKey().encode(buf); + entry.getKey().domainKey().encode(buf); + entry.getKey().contentKey().encode(buf); + entry.getKey().versionKey().encode(buf); // write number of based-on keys buf.writeByte(entry.getValue().size()); // write based-on keys - for (Number160 basedOnKey : entry.getValue()) { - buf.writeBytes(basedOnKey.toByteArray()); + for (final Number160 basedOnKey : entry.getValue()) { + basedOnKey.encode(buf); } } message.contentReferences().poll(); break; case MAP_KEY640_BYTE: - KeyMapByte keysMap = message.keyMapByte(next.index()); + final KeyMapByte keysMap = message.keyMapByte(next.index()); // length buf.writeInt(keysMap.size()); - for (Entry entry : keysMap.keysMap().entrySet()) { - buf.writeBytes(entry.getKey().locationKey().toByteArray()); - buf.writeBytes(entry.getKey().domainKey().toByteArray()); - buf.writeBytes(entry.getKey().contentKey().toByteArray()); - buf.writeBytes(entry.getKey().versionKey().toByteArray()); + for (final Entry entry : keysMap.keysMap().entrySet()) { + entry.getKey().locationKey().encode(buf); + entry.getKey().domainKey().encode(buf); + entry.getKey().contentKey().encode(buf); + entry.getKey().versionKey().encode(buf); buf.writeByte(entry.getValue()); } message.contentReferences().poll(); break; case BYTE_BUFFER: - Buffer buffer = message.buffer(next.index()); - if (!resume) { - buf.writeInt(buffer.length()); - } - // length - int readable = buffer.readable(); - buf.writeBytes(buffer.buffer(), readable); - if (buffer.incRead(readable) == buffer.length()) { - message.contentReferences().poll(); - } else if (message.isStreaming()) { - LOG.debug("Partial message of length {} sent.", readable); - return false; - } else { - final String description = "Larger buffer has been announced, but not in message streaming mode. This is wrong."; - LOG.error(description); - throw new RuntimeException(description); - } + final Buffer buffer = message.buffer(next.index()); + // length + buf.writeInt(buffer.length()); + buf.addComponent(buffer.buffer()); + message.contentReferences().poll(); break; case SET_TRACKER_DATA: - TrackerData trackerData = message.trackerData(next.index()); + final TrackerData trackerData = message.trackerData(next.index()); buf.writeByte(trackerData.peerAddresses().size()); // 1 bytes - length, max. 255 - for (Map.Entry entry : trackerData.peerAddresses().entrySet()) { - byte[] me = entry.getKey().toByteArray(); - buf.writeBytes(me); - Data data = entry.getValue().duplicate(); + for (final Map.Entry entry : trackerData.peerAddresses().entrySet()) { + entry.getKey().encode(buf); + final Data data = entry.getValue().duplicate(); encodeData(buf, data, false, !message.isRequest(), message.command() == Commands.REPLICA_PUT.getNr()); } message.contentReferences().poll(); @@ -229,7 +203,7 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException message.setHintSign(); // then do the regular public key stuff -> no break case PUBLIC_KEY: - PublicKey publicKey = message.publicKey(next.index()); + final PublicKey publicKey = message.publicKey(next.index()); signatureFactory.encodePublicKey(publicKey, buf); message.contentReferences().poll(); break; @@ -237,7 +211,6 @@ private boolean loop(AlternativeCompositeByteBuf buf) throws InvalidKeyException throw new RuntimeException("Unknown type: " + next.content()); } LOG.debug("wrote in encoder for {} {}", content, buf.writerIndex() - start); - } return true; } @@ -255,9 +228,4 @@ private void encodeData(AlternativeCompositeByteBuf buf, Data data, boolean isCo public Message message() { return message; } - - public void reset() { - header = false; - resume = false; - } } diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 76516e574..7f3a441dc 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -20,7 +20,6 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -35,7 +34,8 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.rpc.SimpleBloomFilter; @@ -60,7 +60,7 @@ public class Message { public enum Content { EMPTY, KEY, MAP_KEY640_DATA, MAP_KEY640_KEYS, SET_KEY640, SET_NEIGHBORS, BYTE_BUFFER, LONG, INTEGER, PUBLIC_KEY_SIGNATURE, SET_TRACKER_DATA, BLOOM_FILTER, MAP_KEY640_BYTE, - PUBLIC_KEY, SET_PEER_SOCKET, USER1 + PUBLIC_KEY, PEER_SOCKET4, PEER_SOCKET6 }; /** @@ -188,7 +188,8 @@ public enum Type { private List bufferList = null; private List trackerDataList = null; private List publicKeyList = null; - private List peerSocketAddressList = null; + private List peerSocket4AddressList = null; + private List peerSocket6AddressList = null; private SignatureCodec signatureEncode = null; // this will not be transferred, status variables @@ -879,27 +880,57 @@ public PublicKey publicKey(final int index) { return publicKeyList.get(index); } - public Message peerSocketAddresses(Collection peerSocketAddresses) { + public Message peerSocket4Address(final PeerSocket4Address peerSocket4Address) { if (!presetContentTypes) { - contentType(Content.SET_PEER_SOCKET); + contentType(Content.PEER_SOCKET4); } - if(this.peerSocketAddressList == null) { - this.peerSocketAddressList = new ArrayList(peerSocketAddresses.size()); + if(peerSocket4AddressList == null) { + peerSocket4AddressList = new ArrayList(1); } - this.peerSocketAddressList.addAll(peerSocketAddresses); + peerSocket4AddressList.add(peerSocket4Address); return this; } - public List peerSocketAddresses() { - if (peerSocketAddressList == null) { + public List peerSocket4AddressList() { + if (peerSocket4AddressList == null) { return Collections.emptyList(); } - return peerSocketAddressList; + return peerSocket4AddressList; } - /*public PublicKey getPublicKey() { - return publicKey; - }*/ + public PeerSocket4Address peerSocket4Address(final int index) { + if (peerSocket4AddressList == null || index > peerSocket4AddressList.size() - 1) { + return null; + } + return peerSocket4AddressList.get(index); + } + + public Message peerSocket6Address(final PeerSocket6Address peerSocket6Address) { + if (!presetContentTypes) { + contentType(Content.PEER_SOCKET6); + } + if(peerSocket6AddressList == null) { + peerSocket6AddressList = new ArrayList(1); + } + peerSocket6AddressList.add(peerSocket6Address); + return this; + } + + public List peerSocket6AddressList() { + if (peerSocket6AddressList == null) { + return Collections.emptyList(); + } + return peerSocket6AddressList; + } + + public PeerSocket6Address peerSocket6Address(final int index) { + if (peerSocket6AddressList == null || index > peerSocket6AddressList.size() - 1) { + return null; + } + return peerSocket6AddressList.get(index); + } + + public PrivateKey privateKey() { return privateKey; @@ -1153,7 +1184,8 @@ public Message duplicate(DataFilter dataFilter) { message.bufferList = this.bufferList; message.trackerDataList = this.trackerDataList; message.publicKeyList = this.publicKeyList; - message.peerSocketAddressList = this.peerSocketAddressList; + message.peerSocket4AddressList = this.peerSocket4AddressList; + message.peerSocket6AddressList = this.peerSocket6AddressList; message.signatureEncode = this.signatureEncode; // these are transient, copy anyway @@ -1201,7 +1233,7 @@ private List filter(DataFilter dataFilter) { * Returns the estimated message size. If the message contains data, a constant value of 1000bytes is added. */ public int estimateSize() { - int current = MessageHeaderCodec.HEADER_SIZE; + int current = MessageHeaderCodec.HEADER_SIZE_STATIC + sender.size(); if(neighborsList != null) { for (NeighborSet neighbors : neighborsList) { @@ -1259,10 +1291,12 @@ public int estimateSize() { } } - if(peerSocketAddressList != null) { - for (PeerSocketAddress address : peerSocketAddressList) { - current += address.size() + 1; - } + if(peerSocket4AddressList != null) { + current += (peerSocket4AddressList.size() * PeerSocket4Address.SIZE); + } + + if(peerSocket6AddressList != null) { + current += (peerSocket6AddressList.size() * PeerSocket6Address.SIZE); } if(signatureEncode != null) { diff --git a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java index 87a49a7bc..f3aac237e 100644 --- a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java +++ b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java @@ -15,19 +15,23 @@ */ package net.tomp2p.message; -import io.netty.buffer.ByteBuf; - +import java.net.Inet4Address; import java.net.InetSocketAddress; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.netty.buffer.ByteBuf; import net.tomp2p.message.Message.Content; import net.tomp2p.message.Message.Type; +import net.tomp2p.peers.IP.IPv4; +import net.tomp2p.peers.IP.IPv6; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Encodes and decodes the header of a {@code Message} sing a Netty Buffer. * @@ -44,14 +48,25 @@ public final class MessageHeaderCodec { private MessageHeaderCodec() { } - public static final int HEADER_SIZE = 59; - public static final int HEADER_PRIVATE_ADDRESS_SIZE = 8; + public static final int HEADER_SIZE_STATIC = 34; + public static final int HEADER_SIZE_MIN = HEADER_SIZE_STATIC + PeerAddress.MIN_SIZE_HEADER; //63 /** * Encodes a message object. * - * The format looks as follows: 28bit p2p version - 4bit message type - 32bit message id - 8bit message command - 160bit - * sender id - 16bit sender tcp port - 16bit sender udp port - 160bit recipient id - 32bit content types - 8bit sender options - 8bit message options. It total, + * The format looks as follows: + * - 28bit p2p version + * - 4bit message type //4 bytes + * - 32bit message id //8 bytes + * - 8bit message command //9 bytes + * - 160bit recipient id //29 bytes + * - 32bit content types //33 bytes + * - 8bit message options. //34 bytes + * - sender peeraddress, without current IP (variable). The size is + * determined by the first 3 byte. Minimun size is 29 bytes + * //total minimun 63 bytes + * + * It total, * the header is of size 59 bytes. * * @param buffer @@ -60,23 +75,17 @@ private MessageHeaderCodec() { * The message with the header that will be encoded * @return The buffer passed as an argument */ - public static void encodeHeader(final ByteBuf buffer, final Message message) { + public static void encodeHeader(final ByteBuf buf, final Message message, final boolean ipv6) { final int versionAndType = message.version() << 4 | (message.type().ordinal() & Utils.MASK_0F); - buffer.writeInt(versionAndType); // 4 - buffer.writeInt(message.messageId()); // 8 - buffer.writeByte(message.command()); // 9 - buffer.writeBytes(message.sender().peerId().toByteArray()); // 29 - buffer.writeShort((short) message.sender().tcpPort()); // 31 - buffer.writeShort((short) message.sender().udpPort()); // 33 - buffer.writeBytes(message.recipient().peerId().toByteArray()); // 53 - buffer.writeInt(encodeContentTypes(message.contentTypes())); // 57 + buf.writeInt(versionAndType); // 4 + buf.writeInt(message.messageId()); // 8 + buf.writeByte(message.command()); // 9 + buf.writeBytes(message.recipient().peerId().toByteArray()); // 29 + buf.writeInt(encodeContentTypes(message.contentTypes())); // 33 // three bits for the message options, 5 bits for the sender options - buffer.writeByte(message.sender().options()); //58 - buffer.writeByte(message.options()); // 59 - if(message.sender().isNet4Private()) { - byte[] ext = message.sender().strip().toByteArray(); - buffer.writeBytes(ext); - } + buf.writeByte(message.options()); // 34 + final PeerAddress sender = ipv6 ? message.sender().withSkipIPv6(true) : message.sender().withSkipIPv4(true); + sender.encode(buf); } /** @@ -94,50 +103,43 @@ public static void encodeHeader(final ByteBuf buffer, final Message message) { * The sender of the packet, which has been set in the socket class * @return The partial message where only the header fields are set */ - public static Message decodeHeader(final ByteBuf buffer, final InetSocketAddress recipientSocket, - final InetSocketAddress senderSocket) { + public static boolean decodeHeader(final ByteBuf buffer, final InetSocketAddress recipientSocket, + final InetSocketAddress senderSocket, final Message message) { LOG.debug("Decode message. Recipient: {}, Sender:{}.", recipientSocket, senderSocket); - final Message message = new Message(); final int versionAndType = buffer.readInt(); message.version(versionAndType >>> 4); message.type(Type.values()[(versionAndType & Utils.MASK_0F)]); message.messageId(buffer.readInt()); final int command = buffer.readUnsignedByte(); message.command((byte) command); - final Number160 senderID = readID(buffer); - final int tcpPort = buffer.readUnsignedShort(); - final int udpPort = buffer.readUnsignedShort(); - final Number160 recipientID = readID(buffer); - message.recipient(new PeerAddress(recipientID, recipientSocket)); + final Number160 recipientID = Number160.decode(buffer); + message.recipient(PeerAddress.builder().peerId(recipientID).build()); final int contentTypes = buffer.readInt(); message.hasContent(contentTypes != 0); message.contentTypes(decodeContentTypes(contentTypes, message)); // set the address as we see it, important for port forwarding // identification - final int senderOptions = buffer.readUnsignedByte(); - final PeerAddress peerAddress = new PeerAddress(senderID, - senderSocket.getAddress(), tcpPort, udpPort, senderOptions); final int messageOptions = buffer.readUnsignedByte(); message.options(messageOptions); - message.sender(peerAddress); + final int header = buffer.readUnsignedMedium(); + final int peerAddressSize = PeerAddress.size(header); + if(buffer.readableBytes() < peerAddressSize) { + return false; + } + PeerAddress peerAddress = PeerAddress.decode(buffer); + if(senderSocket.getAddress() instanceof Inet4Address) { + PeerSocket4Address psa4 = peerAddress.ipv4Socket().withIpv4(IPv4.fromInet4Address(senderSocket.getAddress())); + message.sender(peerAddress.withIpv4Socket(psa4)); + } else { + PeerSocket6Address psa6 = peerAddress.ipv6Socket().withIpv6(IPv6.fromInet6Address(senderSocket.getAddress())); + message.sender(peerAddress.withIpv6Socket(psa6)); + } + message.senderSocket(senderSocket); message.recipientSocket(recipientSocket); - return message; - } - - /** - * Reads a {@code Number160} number from a Netty buffer. I did not want to include ChannelBuffer in the class Number160. - * - * @param buffer - * The Netty buffer - * @return A 160bit number from the Netty buffer (deserialized) - */ - private static Number160 readID(final ByteBuf buffer) { - byte[] me = new byte[Number160.BYTE_ARRAY_SIZE]; - buffer.readBytes(me); - return new Number160(me); + return true; } /** diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index 6cbcb49de..d4732421a 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -8,6 +8,7 @@ import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramPacket; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -36,12 +37,14 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann ctx.write(msg, promise); return; } - try { + boolean ipv6 = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress() instanceof Inet6Address; + + try { boolean done = false; buf = AlternativeCompositeByteBuf.compBuffer(byteBufAllocator, buf); - //null, means create signature - done = encoder.write(buf, (Message) msg, null); + //null, means create signature, as we did not have created one already + done = encoder.write(buf, (Message) msg, null, ipv6); final Message message = encoder.message(); @@ -55,14 +58,14 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann //in case of a request if(message.recipientRelay()!=null) { //in case of sending to a relay (the relayed flag is already set) - recipient = message.recipientRelay().createSocketUDP(); + recipient = ipv6 ? message.recipientRelay().ipv6Socket().createUDPSocket(): message.recipientRelay().ipv4Socket().createUDPSocket(); } else if(message.recipientReflected()!=null) { //in case we use nat reflection - recipient = message.recipientReflected().createSocketUDP(); + recipient = ipv6 ? message.recipientReflected().ipv6Socket().createUDPSocket() : message.recipientReflected().ipv4Socket().createUDPSocket(); } else { - recipient = message.recipient().createSocketUDP(); + recipient = ipv6 ? message.recipient().ipv6Socket().createUDPSocket() : message.recipient().ipv4Socket().createUDPSocket(); } - sender = message.sender().createSocketUDP(0); + sender = ipv6 ? message.sender().ipv6Socket().createSocket(0) : message.sender().ipv4Socket().createSocket(0); } else { //in case of a reply recipient = message.senderSocket(); @@ -83,8 +86,6 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann } if (done) { message.setDone(true); - // we wrote the complete message, reset state - encoder.reset(); } } else { buf.release(); diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index cb86eb5f8..4ac03ae7e 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -191,10 +191,10 @@ public Peer start() throws IOException { channelServerConfiguration.behindFirewall(behindFirewall); } if(isTcpPortSet || isUdpPortSet) { - channelServerConfiguration.ports(new Ports(tcpPort, udpPort)); + channelServerConfiguration.ports(new Ports(tcpPort, udpPort, udpPort + 1)); } - channelServerConfiguration.portsForwarding(new Ports(tcpPortForwarding, udpPortForwarding)); + channelServerConfiguration.portsForwarding(new Ports(tcpPortForwarding, udpPortForwarding, udpPortForwarding + 1)); if (channelClientConfiguration == null) { channelClientConfiguration = createDefaultChannelClientConfiguration(); @@ -325,8 +325,8 @@ public static ChannelServerConfiguration createDefaultChannelServerConfiguration ChannelServerConfiguration channelServerConfiguration = new ChannelServerConfiguration(); channelServerConfiguration.bindings(new Bindings()); //these two values may be overwritten in the peer builder - channelServerConfiguration.ports(new Ports(Ports.DEFAULT_PORT, Ports.DEFAULT_PORT)); - channelServerConfiguration.portsForwarding(new Ports(Ports.DEFAULT_PORT, Ports.DEFAULT_PORT)); + channelServerConfiguration.ports(new Ports(Ports.DEFAULT_PORT, Ports.DEFAULT_PORT, Ports.DEFAULT_PORT + 1)); + channelServerConfiguration.portsForwarding(new Ports(Ports.DEFAULT_PORT, Ports.DEFAULT_PORT, Ports.DEFAULT_PORT + 1)); channelServerConfiguration.behindFirewall(false); channelServerConfiguration.pipelineFilter(new DefaultPipelineFilter()); channelServerConfiguration.signatureFactory(new DSASignatureFactory()); diff --git a/core/src/main/java/net/tomp2p/p2p/SlowPeerFilter.java b/core/src/main/java/net/tomp2p/p2p/SlowPeerFilter.java index d69fa4bad..f0a59fa05 100644 --- a/core/src/main/java/net/tomp2p/p2p/SlowPeerFilter.java +++ b/core/src/main/java/net/tomp2p/p2p/SlowPeerFilter.java @@ -12,12 +12,12 @@ public class SlowPeerFilter implements PostRoutingFilter { @Override public boolean rejectPotentialHit(PeerAddress peerAddress) { - return peerAddress.isSlow(); + return peerAddress.slow(); } @Override public boolean rejectDirectHit(PeerAddress peerAddress) { - return peerAddress.isSlow(); + return peerAddress.slow(); } } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java index 72f47b6cb..ecde6be4f 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java @@ -21,6 +21,9 @@ import java.util.ArrayList; import java.util.Collection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import net.tomp2p.connection.Ports; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; @@ -31,15 +34,13 @@ import net.tomp2p.futures.FutureWrappedBootstrap; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.RoutingConfiguration; +import net.tomp2p.peers.IP.IPv4; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Bootstraps to a known peer. First, channels are reserved, then discover(PeerAddress) is called to verify this Internet * connection settings using the "peerAddress" argument . Then the routing is initiated to the peers specified in @@ -122,8 +123,8 @@ public BootstrapBuilder inetSocketAddress(InetSocketAddress socket) { return this; } - public BootstrapBuilder peerSocketAddress(PeerSocketAddress socket) { - this.inetAddress = socket.inetAddress(); + public BootstrapBuilder peerSocketAddress(PeerSocket4Address socket) { + this.inetAddress = socket.ipv4().toInetAddress(); this.portTCP = socket.tcpPort(); this.portUDP = socket.udpPort(); return this; @@ -185,9 +186,9 @@ public FutureBootstrap start() { routingConfiguration = new RoutingConfiguration(8, 10, 2); } if (peerAddress == null && inetAddress != null && bootstrapTo == null) { - peerAddress = new PeerAddress(Number160.ZERO, inetAddress, portTCP, portUDP); + PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inetAddress)).tcpPort(portTCP).udpPort(portUDP).build(); + PeerAddress peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(Number160.ZERO).build(); return bootstrapPing(peerAddress); - } if (peerAddress != null && bootstrapTo == null) { bootstrapTo = new ArrayList(1); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 39881da8f..906414606 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -37,7 +37,8 @@ import net.tomp2p.p2p.PeerReachable; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.IP.IPv4; import net.tomp2p.utils.Utils; import org.slf4j.Logger; @@ -55,6 +56,7 @@ public class DiscoverBuilder { private int portUDP = Ports.DEFAULT_PORT; private int portTCP = Ports.DEFAULT_PORT; + //private int portUDT = Ports.DEFAULT_PORT + 1; private PeerAddress peerAddress; @@ -93,8 +95,8 @@ public DiscoverBuilder inetSocketAddress(InetAddress inetAddress, int portTCP, i return this; } - public DiscoverBuilder peerSocketAddress(PeerSocketAddress peerSocketAddress) { - this.inetAddress = peerSocketAddress.inetAddress(); + public DiscoverBuilder peerSocketAddress(PeerSocket4Address peerSocketAddress) { + this.inetAddress = peerSocketAddress.ipv4().toInetAddress(); this.portTCP = peerSocketAddress.tcpPort(); this.portUDP = peerSocketAddress.udpPort(); return this; @@ -170,7 +172,8 @@ public FutureDiscover start() { } if (peerAddress == null && inetAddress != null) { - peerAddress = new PeerAddress(Number160.ZERO, inetAddress, portTCP, portUDP); + PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inetAddress)).tcpPort(portTCP).udpPort(portUDP).build(); + peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(Number160.ZERO).build(); } if (peerAddress == null) { throw new IllegalArgumentException("Peer address or inet address required."); @@ -264,7 +267,7 @@ public void operationComplete(FutureResponse future) throws Exception { } else if (futureResponseTCP.isSuccess()) { //now we know our internal address, set it as it could be a wrong one, e.g. 127.0.0.1 - serverAddress = serverAddress.changeAddress(futureResponseTCP.responseMessage().recipient().inetAddress()); + serverAddress = serverAddress.withIpv4Socket(futureResponseTCP.responseMessage().recipient().ipv4Socket()); Collection tmp = futureResponseTCP.responseMessage().neighborsSet(0) .neighbors(); @@ -272,18 +275,18 @@ else if (futureResponseTCP.isSuccess()) { if (tmp.size() == 1) { PeerAddress seenAs = tmp.iterator().next(); LOG.info("This peer is seen as {} by peer {}. This peer sees itself as {}.", - seenAs, peerAddress, peer.peerAddress().inetAddress()); - if (!peer.peerAddress().inetAddress().equals(seenAs.inetAddress())) { + seenAs, peerAddress, peer.peerAddress()); + if (!peer.peerAddress().ipv4Socket().equalsWithoutPorts(seenAs.ipv4Socket())) { // check if we have this interface in that we can // listen to - Bindings bindings2 = new Bindings().addAddress(seenAs.inetAddress()); + Bindings bindings2 = new Bindings().addAddress(seenAs.ipv4Socket().ipv4().toInetAddress()); DiscoverResults discoverResults = DiscoverNetworks.discoverInterfaces(bindings2); String status = discoverResults.status(); LOG.info("2nd interface discovery: {}", status); if (discoverResults.newAddresses().size() > 0 - && discoverResults.newAddresses().contains(seenAs.inetAddress())) { - serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); + && discoverResults.newAddresses().contains(seenAs.ipv4Socket().ipv4().toInetAddress())) { + serverAddress = serverAddress.withIpv4Socket(seenAs.ipv4Socket()); peer.peerBean().serverPeerAddress(serverAddress); LOG.info("This peer had the wrong interface. Changed it to {}.", serverAddress); } else { @@ -292,27 +295,24 @@ else if (futureResponseTCP.isSuccess()) { final Ports ports = peer.connectionBean().channelServer().channelServerConfiguration().portsForwarding(); if (ports.isManualPort()) { final PeerAddress serverAddressOrig = serverAddress; - serverAddress = serverAddress.changePorts(ports.tcpPort(), - ports.udpPort()); - serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); + PeerSocket4Address serverSocket = serverAddress.ipv4Socket(); + serverSocket = serverSocket.withTcpPort(ports.tcpPort()).withUdpPort(ports.udpPort()); + serverSocket = serverSocket.withIpv4(seenAs.ipv4Socket().ipv4()); //manual port forwarding detected, set flag - serverAddress = serverAddress.changePortForwarding(true); - serverAddress = serverAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); - peer.peerBean().serverPeerAddress(serverAddress); + peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket).withIpInternalSocket(serverAddressOrig.ipv4Socket())); LOG.info("manual ports, change it to: {}", serverAddress); } else if(expectManualForwarding) { final PeerAddress serverAddressOrig = serverAddress; - serverAddress = serverAddress.changePortForwarding(true); - serverAddress = serverAddress.changeAddress(seenAs.inetAddress()); - serverAddress = serverAddress.changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); - peer.peerBean().serverPeerAddress(serverAddress); + PeerSocket4Address serverSocket = serverAddress.ipv4Socket(); + serverSocket = serverSocket.withIpv4(seenAs.ipv4Socket().ipv4()); + peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket).withIpInternalSocket(serverAddressOrig.ipv4Socket())); LOG.info("we were manually forwarding, change it to: {}", serverAddress); } else { // we need to find a relay, because there is a NAT in the way. // we cannot use futureResponseTCP.responseMessage().recipient() as this may return also IPv6 addresses - LOG.info("We are most likely behind NAT, try to UPNP, NATPMP or relay. PeerAddress: {}, ServerAddress: {}, Seen as: {}" + peerAddress, serverAddress.inetAddress(), seenAs.inetAddress()); - futureDiscover.externalHost("We are most likely behind NAT, try to UPNP, NATPMP or relay. Using peerAddress " + peerAddress, serverAddress.inetAddress(), seenAs.inetAddress()); + LOG.info("We are most likely behind NAT, try to UPNP, NATPMP or relay. PeerAddress: {}, ServerAddress: {}, Seen as: {}" + peerAddress, serverAddress, seenAs); + futureDiscover.externalHost("We are most likely behind NAT, try to UPNP, NATPMP or relay. Using peerAddress " + peerAddress, serverAddress.ipv4Socket(), seenAs.ipv4Socket()); return; } } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java index 4b262217b..33dee65a3 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/PingBuilder.java @@ -32,8 +32,10 @@ import net.tomp2p.futures.FuturePing; import net.tomp2p.futures.FutureResponse; import net.tomp2p.p2p.Peer; +import net.tomp2p.peers.IP.IPv4; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.utils.Utils; public class PingBuilder { @@ -155,9 +157,9 @@ public FuturePing start() { } } else if (inetAddress != null) { if (tcpPing) { - return ping(new InetSocketAddress(inetAddress, port), Number160.ZERO, false); + return ping(inetAddress, port, Number160.ZERO, false); } else { - return ping(new InetSocketAddress(inetAddress, port), Number160.ZERO, true); + return ping(inetAddress, port, Number160.ZERO, true); } } else if (peerConnection != null) { return pingPeerConnection(peerConnection); @@ -177,8 +179,10 @@ public FuturePing start() { * Set to true if UDP should be used, false for TCP. * @return The future response */ - private FuturePing ping(final InetSocketAddress address, final Number160 peerId, final boolean isUDP) { - return ping(new PeerAddress(peerId, address), isUDP); + private FuturePing ping(final InetAddress address, int port, final Number160 peerId, final boolean isUDP) { + PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(address)).tcpPort(port).udpPort(port).build(); + PeerAddress peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(peerId).build(); + return ping(peerAddress, isUDP); } /** @@ -241,9 +245,10 @@ public void operationComplete(FutureChannelCreator future) throws Exception { if (future.isSuccess()) { addPingListener(futurePing, futureLateJoin); for (InetAddress broadcastAddress: discoverResults.existingBroadcastAddresses()) { - final PeerAddress peerAddress = new PeerAddress(Number160.ZERO, broadcastAddress, - port, port); - FutureResponse validBroadcast = peer.pingRPC().pingBroadcastUDP( + + PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(broadcastAddress)).tcpPort(port).udpPort(port).build(); + PeerAddress peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(Number160.ZERO).build(); + FutureResponse validBroadcast = peer.pingRPC().pingBroadcastUDP( peerAddress, future.channelCreator(), connectionConfiguration); if (!futureLateJoin.add(validBroadcast)) { // the latejoin future is finished if the add returns false diff --git a/core/src/main/java/net/tomp2p/peers/IP.java b/core/src/main/java/net/tomp2p/peers/IP.java index de9e4854c..89de34d04 100644 --- a/core/src/main/java/net/tomp2p/peers/IP.java +++ b/core/src/main/java/net/tomp2p/peers/IP.java @@ -5,11 +5,11 @@ import java.net.InetAddress; import java.net.UnknownHostException; -public class IP { - public static class IPv4 { +public abstract class IP { + public static class IPv4 extends IP { private final int bits; - private IPv4(int bits) { + private IPv4(final int bits) { this.bits = bits; } @@ -23,7 +23,7 @@ public IPv4 maskWithNetworkMask(final int networkMask) { return new IPv4(0); } else { - int mask = (0xFFFFFFFF << (32 - networkMask)); + final int mask = (0xFFFFFFFF << (32 - networkMask)); return new IPv4(bits & mask); } } @@ -39,13 +39,13 @@ public IPv4 maskWithNetworkMaskInv(final int networkMask) { } } - public IPv4 set(IPv4 maskedAddress) { - int newBits = bits | maskedAddress.bits; + public IPv4 set(final IPv4 maskedAddress) { + final int newBits = bits | maskedAddress.bits; return new IPv4(newBits); } public InetAddress toInetAddress() { - byte[] ip = new byte[4]; + final byte[] ip = new byte[4]; ip[0] = (byte) (bits >>> 24); ip[1] = (byte) (bits >>> 16); ip[2] = (byte) (bits >>> 8); @@ -58,6 +58,10 @@ public InetAddress toInetAddress() { return null; } } + + public int toInt() { + return bits; + } @Override public boolean equals(Object obj) { @@ -67,7 +71,7 @@ public boolean equals(Object obj) { if (!(obj instanceof IPv4)) { return false; } - IPv4 o = (IPv4) obj; + final IPv4 o = (IPv4) obj; return bits == o.bits; } @@ -92,11 +96,11 @@ public String toString() { - public static class IPv6 { + public static class IPv6 extends IP { private final long highBits; private final long lowBits; - private IPv6(long highBits, long lowBits) { + private IPv6(final long highBits, final long lowBits) { this.highBits = highBits; this.lowBits = lowBits; } @@ -114,8 +118,8 @@ public IPv6 maskWithNetworkMask(final int networkMask) { } } - public InetAddress toInetAddress() throws UnknownHostException { - byte[] ip = new byte[16]; + public InetAddress toInetAddress() { + final byte[] ip = new byte[16]; ip[0] = (byte) (highBits >>> 56); ip[1] = (byte) (highBits >>> 48); ip[2] = (byte) (highBits >>> 40); @@ -132,7 +136,21 @@ public InetAddress toInetAddress() throws UnknownHostException { ip[13] = (byte) (lowBits >>> 16); ip[14] = (byte) (lowBits >>> 8); ip[15] = (byte) (lowBits); - return Inet4Address.getByAddress(ip); + try { + return Inet6Address.getByAddress(ip); + } catch (UnknownHostException e) { + //we know the size, so this should not throw an exception + e.printStackTrace(); + return null; + } + } + + public long toLongHi() { + return highBits; + } + + public long toLongLo() { + return lowBits; } @Override @@ -143,7 +161,7 @@ public boolean equals(Object obj) { if (!(obj instanceof IPv6)) { return false; } - IPv6 o = (IPv6) obj; + final IPv6 o = (IPv6) obj; return highBits == o.highBits && lowBits == o.lowBits; } @@ -174,32 +192,42 @@ public String toString() { } } + public abstract InetAddress toInetAddress(); + + public static IPv4 fromInt(final int bits) { + return new IPv4(bits); + } + public static IPv4 fromInet4Address(final InetAddress inetAddress) { if (inetAddress == null) { throw new IllegalArgumentException("Cannot construct from null."); } else if (!(inetAddress instanceof Inet4Address)) { throw new IllegalArgumentException("Must be IPv4."); } - byte[] buf = ((Inet4Address) inetAddress).getAddress(); + final byte[] buf = ((Inet4Address) inetAddress).getAddress(); - int ip = ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) + final int ip = ((buf[0] & 0xFF) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | ((buf[3] & 0xFF)); return new IPv4(ip); } + public static IPv6 fromLong(long highBits, long lowBits) { + return new IPv6(highBits, lowBits); + } + public static IPv6 fromInet6Address(final InetAddress inetAddress) { if (inetAddress == null) { throw new IllegalArgumentException("Cannot construct from null."); } else if (!(inetAddress instanceof Inet6Address)) { throw new IllegalArgumentException("Must be IPv6."); } - byte[] buf = ((Inet6Address) inetAddress).getAddress(); + final byte[] buf = ((Inet6Address) inetAddress).getAddress(); - long highBits = ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) | ((buf[2] & 0xFFL) << 40) + final long highBits = ((buf[0] & 0xFFL) << 56) | ((buf[1] & 0xFFL) << 48) | ((buf[2] & 0xFFL) << 40) | ((buf[3] & 0xFFL) << 32) | ((buf[4] & 0xFFL) << 24) | ((buf[5] & 0xFFL) << 16) | ((buf[6] & 0xFFL) << 8) | ((buf[7] & 0xFFL)); - long lowBits = ((buf[8] & 0xFFL) << 56) | ((buf[9] & 0xFFL) << 48) | ((buf[10] & 0xFFL) << 40) + final long lowBits = ((buf[8] & 0xFFL) << 56) | ((buf[9] & 0xFFL) << 48) | ((buf[10] & 0xFFL) << 40) | ((buf[11] & 0xFFL) << 32) | ((buf[12] & 0xFFL) << 24) | ((buf[13] & 0xFFL) << 16) | ((buf[14] & 0xFFL) << 8) | ((buf[15] & 0xFFL)); diff --git a/core/src/main/java/net/tomp2p/peers/Number160.java b/core/src/main/java/net/tomp2p/peers/Number160.java index 5b6a524f6..3f2cb8863 100644 --- a/core/src/main/java/net/tomp2p/peers/Number160.java +++ b/core/src/main/java/net/tomp2p/peers/Number160.java @@ -17,6 +17,8 @@ import java.util.Random; +import io.netty.buffer.ByteBuf; +import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; /** @@ -253,6 +255,7 @@ public int[] toIntArray() { * where to start in the byte array * @return the offset we have read */ + @Deprecated public int toByteArray(final byte[] me, final int offset) { if (offset + BYTE_ARRAY_SIZE > me.length) { throw new RuntimeException("array too small"); @@ -472,4 +475,22 @@ public static Number160 createHash(final long longValue) { public static Number160 createHash(final String string) { return Utils.makeSHAHash(string); } + + public static Pair decode(byte[] me, int offset) { + Number160 number160 = new Number160(me, offset, 20); + return new Pair(number160, offset + 20); + } + + public static Number160 decode(ByteBuf buf) { + return new Number160(buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt()); + } + + public int encode(byte[] me, int offset) { + return toByteArray(me, offset); + } + + public Number160 encode(ByteBuf buf) { + buf.writeInt(val[0]).writeInt(val[1]).writeInt(val[2]).writeInt(val[3]).writeInt(val[4]).writeInt(val[5]); + return this; + } } diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 83db380e1..9184632cf 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -15,23 +15,21 @@ */ package net.tomp2p.peers; -import io.netty.buffer.ByteBuf; - import java.io.Serializable; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.InterfaceAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Arrays; import java.util.BitSet; import java.util.Collection; import java.util.Collections; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.Wither; +import net.tomp2p.peers.IP.IPv4; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; +import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; /** @@ -56,38 +54,78 @@ * * @author Thomas Bocek */ -public final class PeerAddress implements Comparable, Serializable { - - public static final int MAX_SIZE = 142; - public static final int MIN_SIZE = 30; - private static final long serialVersionUID = -1316622724169272306L; - private static final int NET6 = 1; // 0000001 - private static final int FIREWALL_UDP = 2; // 0000010 - private static final int FIREWALL_TCP = 4; // 0000100 - // indicates that a relay is used. - private static final int RELAYED = 8; // 0001000 - // indicates that the peer is slow (because relayed) - private static final int SLOW = 16; // 0010000 - // indicates the peer forwarded the ports either manually or with UPNP - private static final int PORT_FORWARDING = 32; // 0100000 +@Builder +@Accessors(fluent = true, chain = true) +public final class PeerAddress implements Comparable, Serializable { + + private static final long serialVersionUID = 8483270473601620720L; + + public static final int HEADER_SIZE = 3; + public static final int MIN_SIZE = HEADER_SIZE + Number160.BYTE_ARRAY_SIZE; //23 + public static final int MIN_SIZE_HEADER = MIN_SIZE + 6; //29 + public static final int MAX_SIZE = MIN_SIZE + (2 * PeerSocket4Address.SIZE) + (8 * PeerSocket6Address.SIZE); //219 + + //1 Byte - 8 bits + private static final int IPV4 = 0x1; // xxxxxxxx xxxxxxxx xxxxxxx1 + private static final int IPV6 = 0x2; // xxxxxxxx xxxxxxxx xxxxxx1x + + private static final int REACHABLE4_UDP = 0x4; // xxxxxxxx xxxxxxxx xxxxx1xx + private static final int REACHABLE4_TCP = 0x8; // xxxxxxxx xxxxxxxx xxxx1xxx + private static final int REACHABLE4_UDT = 0x10; // xxxxxxxx xxxxxxxx xxx1xxxx + + private static final int REACHABLE6_UDP = 0x20; // xxxxxxxx xxxxxxxx xx1xxxxx + private static final int REACHABLE6_TCP = 0x40; // xxxxxxxx xxxxxxxx x1xxxxxx + private static final int REACHABLE6_UDT = 0x80; // xxxxxxxx xxxxxxxx 1xxxxxxx + + //next 1 Byte - 8 bits + private static final int RELAY_SIZE_MASK = 0x700; // xxxxxxxx xxxxx111 xxxxxxxx + // indicates that a relay is used. If its relayed it can be slow (buffered) or holepunching + // xxxxxxxx xxx00xxx xxxxxxxx - no flags + private static final int HOLE_PUNCHING = 0x1000; // xxxxxxxx xxx10xxx xxxxxxxx + // if relayed, indicates that the peer is slow + private static final int SLOW = 0x800; // xxxxxxxx xxx01xxx xxxxxxxx + // if relayed, indicate if HP is possible + private static final int RELAY_FLAGS_MASK = 0x1800; // xxxxxxxx xxx11xxx xxxxxxxx - unused + private static final int UNREACHABLE = 0x2000; // xxxxxxxx xx1xxxxx xxxxxxxx // indicate IPv4 with the internal IP - private static final int NET4_PRIVATE = 64; // 1000000 + private static final int NET4_INTERNAL = 0x4000; // xxxxxxxx x1xxxxxx xxxxxxxx //hopefully we'll never use this for IPv6 + private static final int SKIP_IPV4 = 0x8000; // xxxxxxxx 1xxxxxxx xxxxxxxx + private static final int SKIP_IPV6 = 0x10000; // xxxxxxx1 xxxxxxxx xxxxxxxx + + //next 1 Byte - 8 bits - we can have at most 7 relays + private static final int RELAY_TYPE_MASK = 0xfe0000; // 1111111x xxxxxxxx xxxxxxxx + + @Getter @Wither private final PeerSocket4Address ipInternalSocket; + @Getter @Wither private final int ipInternalNetworkPrefix; + // + @Getter @Wither private final PeerSocket4Address ipv4Socket; + @Getter @Wither private final PeerSocket6Address ipv6Socket; + + @Getter @Wither private final boolean ipv4Flag; + @Getter @Wither private final boolean ipv6Flag; + + //@Getter @Wither private final boolean net6Flag; // unused + @Getter @Wither private final boolean reachable4UDP; + @Getter @Wither private final boolean reachable4TCP; + @Getter @Wither private final boolean reachable4UDT; + @Getter @Wither private final boolean reachable6UDP; + @Getter @Wither private final boolean reachable6TCP; + @Getter @Wither private final boolean reachable6UDT; // network information - private final Number160 peerId; - private final PeerSocketAddress peerSocketAddress; - private final PeerSocketAddress internalPeerSocketAddress; - private final int internalNetworkPrefix; - + @Getter @Wither private final Number160 peerId; // connection information - private final boolean net6; - private final boolean firewalledUDP; - private final boolean firewalledTCP; - private final boolean relayed; - private final boolean slow; - private final boolean portForwarding; - private final boolean net4Private; + @Getter @Wither private final int relaySize; + @Getter @Wither private final boolean slow; + @Getter @Wither private final boolean holePunching; + //@Getter @Wither private final boolean relayFlag; // unused + @Getter @Wither private final boolean unreachable; + @Getter @Wither private final boolean net4Internal; + @Getter @Wither private final boolean skipIPv4; + @Getter @Wither private final boolean skipIPv6; + + @Wither private final BitSet relayTypes; // we can make the hash final as it never changes, and this class is used // multiple times in maps. A new peer is always added to the peermap, so @@ -97,28 +135,100 @@ public final class PeerAddress implements Comparable, Serializable // added to the peermap. private final int hashCode; - // if deserialized from a byte array using the constructor, then we need to - // report how many data we processed. - private final int offset; - - private final int size; - private final int relaySize; - private final BitSet relayType; - private static final BitSet EMPTY_RELAY_TYPE = new BitSet(0); //relays - private final Collection peerSocketAddresses; + private final Collection relays; public static final Collection EMPTY_PEER_SOCKET_ADDRESSES = Collections.emptySet(); - - private static final int TYPE_BIT_SIZE = 5; - private static final int HEADER_SIZE = 2; - // count both ports, UDP and TCP - private static final int PORTS_SIZE = 4; + public static final byte EMPTY_RELAY_TYPES = 0; - // used for the relay bit shifting - private static final int MASK_1F = 0x1f; // 0001 1111 - private static final int MASK_07 = 0x7; // 0000 0111 + //Change lomboks default behavior + public static class PeerAddressBuilder { + public PeerAddressBuilder relay(PeerSocketAddress relay) { + if(relaySize == 7) { + throw new IllegalArgumentException("cannot have more than 7 relays"); + } + if (this.relays == null) { + this.relays = new ArrayList(1); + } + if(this.relayTypes == null) { + this.relayTypes = new BitSet(8); + } + if(relay instanceof PeerSocket4Address) { + this.relayTypes.set(this.relaySize++, false); + } + else { + this.relayTypes.set(this.relaySize++, true); + } + this.relays.add(relay); + return this; + } + + private PeerAddressBuilder relay(PeerSocketAddress relay, int index) { + if(relaySize > 7) { + throw new IllegalArgumentException("cannot have more than 7 relays"); + } + if (this.relays == null) { + this.relays = new ArrayList(relaySize); + } + if(this.relayTypes == null) { + this.relayTypes = new BitSet(8); + } + if(relay instanceof PeerSocket4Address) { + this.relayTypes.set(index, false); + } + else { + this.relayTypes.set(index, true); + } + this.relays.add(relay); + return this; + } - + public PeerAddressBuilder relay(Collection relays) { + if (this.relays == null) { + this.relays = new ArrayList(relays.size()); + } + + for (PeerSocketAddress relay : relays) { + relay(relay); + } + return this; + } + + public PeerAddressBuilder ipv4Socket(PeerSocket4Address ipv4Socket) { + this.ipv4Flag = true; + this.ipv4Socket = ipv4Socket; + return this; + } + + public PeerAddressBuilder ipv6Socket(PeerSocket6Address ipv6Socket) { + this.ipv6Flag = true; + this.ipv6Socket = ipv6Socket; + return this; + } + + public PeerAddressBuilder ipInternalSocket(PeerSocket4Address ipInternalSocket) { + this.net4Internal = true; + this.ipInternalSocket = ipInternalSocket; + return this; + } + + } + + + + public Collection relays() { + if(relays == null) { + return EMPTY_PEER_SOCKET_ADDRESSES; + } + return relays; + } + + public byte relayTypes() { + if(relayTypes == null) { + return EMPTY_RELAY_TYPES; + } + byte[] tmp = relayTypes.toByteArray(); + return tmp.length != 1 ? EMPTY_RELAY_TYPES : tmp[0]; + } /** * Creates a peer address, where the byte array has to be in the rigth format and in the right size. The new @@ -127,8 +237,8 @@ public final class PeerAddress implements Comparable, Serializable * @param me * The serialized array */ - public PeerAddress(final byte[] me) { - this(me, 0); + public static Pair decode(final byte[] array) { + return decode(array, 0); } /** @@ -140,61 +250,46 @@ public PeerAddress(final byte[] me) { * @param initialOffset * the offset, where to start */ - public PeerAddress(final byte[] me, final int initialOffset) { - // get the peer ID, this is independent of the type - int offset = initialOffset; - // get the type - final int options = me[offset++] & Utils.MASK_FF; - this.net6 = (options & NET6) > 0; - this.firewalledUDP = (options & FIREWALL_UDP) > 0; - this.firewalledTCP = (options & FIREWALL_TCP) > 0; - this.relayed = (options & RELAYED) > 0; - this.slow = (options & SLOW) > 0; - this.portForwarding = (options & PORT_FORWARDING) > 0; - this.net4Private = (options & NET4_PRIVATE) > 0; - final int relays = me[offset++] & Utils.MASK_FF; - // first: three bits are the size 1,2,4 - // 000 means no relays - // 001 means 1 relay - // 010 means 2 relays - // 011 means 3 relays - // 100 means 4 relays - // 101 means 5 relays - // 110 is not used - // 111 is not used - // second: five bits indicate if IPv6 or IPv4 -> in total we can save 5 addresses - this.relaySize = (relays >>> TYPE_BIT_SIZE) & MASK_07; - final byte b = (byte) (relays & MASK_1F); - this.relayType = Utils.createBitSet(b); - // now comes the ID - final byte[] tmp = new byte[Number160.BYTE_ARRAY_SIZE]; - System.arraycopy(me, offset, tmp, 0, Number160.BYTE_ARRAY_SIZE); - this.peerId = new Number160(tmp); - offset += Number160.BYTE_ARRAY_SIZE; - - this.peerSocketAddress = PeerSocketAddress.create(me, isIPv4(), offset); - offset = this.peerSocketAddress.offset(); - if(isNet4Private()) { - this.internalPeerSocketAddress = PeerSocketAddress.create(me, true, offset); - offset = this.internalPeerSocketAddress.offset(); - } else { - this.internalPeerSocketAddress = null; - } - this.internalNetworkPrefix = -1; - - if (relaySize > 0) { - this.peerSocketAddresses = new ArrayList(relaySize); - for (int i = 0; i < relaySize; i++) { - PeerSocketAddress psa = PeerSocketAddress.create(me, !relayType.get(i), offset); - peerSocketAddresses.add(psa); - offset = psa.offset(); - } - } else { - this.peerSocketAddresses = EMPTY_PEER_SOCKET_ADDRESSES; - } - this.size = offset - initialOffset; - this.offset = offset; - this.hashCode = peerId.hashCode(); + public static Pair decode(final byte[] array, int offset) { + final PeerAddressBuilder builder = new PeerAddressBuilder(); + + final int header = Utils.byteArrayToMedium(array, offset); + offset+=3; + + decodeHeader(builder, header); + + //relays + for(int i = 0; i pair; + if(builder.relayTypes.get(i)) { + builder.relay((pair = PeerSocket6Address.decode(array, offset)).element0(), i); + } else { + builder.relay((pair = PeerSocket4Address.decode(array, offset)).element0(), i); + } + offset = pair.element1(); + } + + if(builder.ipv4Flag) { + final Pair pair; + builder.ipv4Socket((pair = PeerSocket4Address.decode(array, offset, builder.skipIPv4)).element0()); + offset = pair.element1(); + } + if(builder.net4Internal) { + final Pair pair; + builder.ipInternalSocket((pair = PeerSocket4Address.decode(array, offset)).element0()); + offset = pair.element1(); + } + if(builder.ipv6Flag) { + final Pair pair; + builder.ipv6Socket((pair = PeerSocket6Address.decode(array, offset, builder.skipIPv6)).element0()); + offset = pair.element1(); + } + + final Pair pair; + final PeerAddress peerAddress = builder.peerId((pair = Number160.decode(array, offset)).element0()) + .hashCode(builder.peerId.hashCode()) + .build(); + return new Pair(peerAddress, pair.element1()); } /** @@ -203,235 +298,90 @@ public PeerAddress(final byte[] me, final int initialOffset) { * @param channelBuffer * The channel buffer to read from */ - public PeerAddress(final ByteBuf channelBuffer) { - // get the peer ID, this is independent of the type - - int readerIndex = channelBuffer.readerIndex(); - // get the type - final int options = channelBuffer.readUnsignedByte(); - this.net6 = (options & NET6) > 0; - this.firewalledUDP = (options & FIREWALL_UDP) > 0; - this.firewalledTCP = (options & FIREWALL_TCP) > 0; - this.relayed = (options & RELAYED) > 0; - this.slow = (options & SLOW) > 0; - this.portForwarding = (options & PORT_FORWARDING) > 0; - this.net4Private = (options & NET4_PRIVATE) > 0; - final int relays = channelBuffer.readUnsignedByte(); - // first: three bits are the size 1,2,4 - // 000 means no relays - // 001 means 1 relay - // 010 means 2 relays - // 011 means 3 relays - // 100 means 4 relays - // 101 means 5 relays - // 110 is not used - // 111 is not used - // second: five bits indicate if IPv6 or IPv4 -> in total we can save 5 addresses - this.relaySize = (relays >>> TYPE_BIT_SIZE) & MASK_07; - final byte b = (byte) (relays & MASK_1F); - this.relayType = Utils.createBitSet(b); - // now comes the ID - byte[] me = new byte[Number160.BYTE_ARRAY_SIZE]; - channelBuffer.readBytes(me); - this.peerId = new Number160(me); - - this.peerSocketAddress = PeerSocketAddress.create(channelBuffer, isIPv4()); - this.internalPeerSocketAddress = isNet4Private() ? PeerSocketAddress.create(channelBuffer, true) : null; - this.internalNetworkPrefix = -1; - - if (relaySize > 0) { - this.peerSocketAddresses = new ArrayList(relaySize); - for (int i = 0; i < relaySize; i++) { - this.peerSocketAddresses.add(PeerSocketAddress.create(channelBuffer, !relayType.get(i))); - } - } else { - this.peerSocketAddresses = EMPTY_PEER_SOCKET_ADDRESSES; - } - - this.size = channelBuffer.readerIndex() - readerIndex; - // not used here - this.offset = -1; - this.hashCode = peerId.hashCode(); - } - - /** - * If you only need to know the id. - * - * @param id - * The id of the peer - */ - public PeerAddress(final Number160 id) { - this(id, (InetAddress) null, -1, -1); - } - - /** - * If you only need to know the id and InetAddress. - * - * @param id - * The id of the peer - * @param address - * The InetAddress of the peer - */ - public PeerAddress(final Number160 id, final InetAddress address) { - this(id, address, -1, -1); - } - - /** - * Creates a PeerAddress if all the values are known. - * - * @param id - * The id of the peer - * @param peerSocketAddress - * The peer socket address including both ports UDP and TCP - * @param firewalledUDP - * Indicates if peer is not reachable via UDP - * @param firewalledTCP - * Indicates if peer is not reachable via TCP - * @param isRelayed - * Indicates if peer is used as a relay - * @param isSlow - * Indicates if a peer is slow - * @param peerSocketAddresses - * the relay peers - */ - public PeerAddress(final Number160 id, final PeerSocketAddress peerSocketAddress, final PeerSocketAddress internalPeerSocketAddress, - final boolean firewalledTCP, final boolean firewalledUDP, final boolean isRelayed, - boolean isSlow, boolean portForwarding, boolean net4Private, final Collection peerSocketAddresses) { - this.peerId = id; - int size = Number160.BYTE_ARRAY_SIZE; - this.peerSocketAddress = peerSocketAddress; - this.internalPeerSocketAddress = internalPeerSocketAddress; - this.internalNetworkPrefix = internalPeerSocketAddress == null ? -1: prefix4(internalPeerSocketAddress.inetAddress()); - this.hashCode = id.hashCode(); - this.net6 = peerSocketAddress.inetAddress() instanceof Inet6Address; - this.firewalledUDP = firewalledUDP; - this.firewalledTCP = firewalledTCP; - this.relayed = isRelayed; - this.slow = isSlow; - this.portForwarding = portForwarding; - this.net4Private = net4Private; - // header + TCP port + UDP port - size += HEADER_SIZE + PORTS_SIZE + (net6 ? Utils.IPV6_BYTES : Utils.IPV4_BYTES); - size += net4Private? Utils.IPV4_BYTES + PORTS_SIZE : 0; - if (peerSocketAddresses == null) { - this.peerSocketAddresses = EMPTY_PEER_SOCKET_ADDRESSES; - this.relayType = EMPTY_RELAY_TYPE; - relaySize = 0; - } else { - relaySize = peerSocketAddresses.size(); - if (relaySize > TYPE_BIT_SIZE) { - throw new IllegalArgumentException(String.format("Can only store up to %s relay peers. Tried to store %s relay peers.", TYPE_BIT_SIZE , relaySize)); - } - this.peerSocketAddresses = peerSocketAddresses; - this.relayType = new BitSet(relaySize); - } - int index = 0; - for(PeerSocketAddress psa : this.peerSocketAddresses) { - boolean isIPV6 = psa.inetAddress() instanceof Inet6Address; - this.relayType.set(index, isIPV6); - size += psa.size(); - index++; - } - this.size = size; - // unused here - this.offset = -1; - } - - /** - * Facade for PeerAddress(Number160, PeerSocketAddress, boolean, boolean, boolean, Collection-PeerSocketAddress>). - * - * @param peerId - * The id of the peer - * @param inetAddress - * The internet address of the peer - * @param tcpPort - * The TCP port of the peer - * @param udpPort - * The UDP port of the peer - */ - public PeerAddress(final Number160 peerId, final InetAddress inetAddress, final int tcpPort, - final int udpPort) { - this(peerId, new PeerSocketAddress(inetAddress, tcpPort, udpPort), null, false, false, false, false, false, false, EMPTY_PEER_SOCKET_ADDRESSES); - } - - /** - * Facade for PeerAddress(...) - * - * @param id - * The id of the peer - * @param inetAddress - * The address of the peer, how to reach this peer - * @param tcpPort - * The TCP port how to reach the peer - * @param udpPort - * The UDP port how to reach the peer - * @param options - * The options for the created PeerAddress. - */ - public PeerAddress(final Number160 id, final InetAddress inetAddress, final int tcpPort, - final int udpPort, final int options) { - this(id, new PeerSocketAddress(inetAddress, tcpPort, udpPort), null, isFirewalledTCP(options), - isFirewalledUDP(options), isRelay(options), isSlow(options), isPortForwarding(options), - isNet4Private(options), EMPTY_PEER_SOCKET_ADDRESSES); - } - - /** - * Facade for PeerAddress(Number160, InetAddress, int, int). - * - * @param id - * The id of the peer - * @param address - * The address of the peer, how to reach this peer - * @param tcpPort - * The TCP port how to reach the peer - * @param udpPort - * The UDP port how to reach the peer - * @throws UnknownHostException - * If no IP address for the host could be found, or if a scope_id was specified for a global IPv6 - * address. - */ - public PeerAddress(final Number160 id, final String address, final int tcpPort, final int udpPort) - throws UnknownHostException { - this(id, InetAddress.getByName(address), tcpPort, udpPort); - } - - /** - * Facade for PeerAddress(Number160, InetAddress, int, int). - * - * @param id - * The id of the peer - * @param inetSocketAddress - * The socket address of the peer, how to reach this peer. Both TCP and UDP will be set to the same port - */ - public PeerAddress(final Number160 id, final InetSocketAddress inetSocketAddress) { - this(id, inetSocketAddress.getAddress(), inetSocketAddress.getPort(), inetSocketAddress.getPort()); - } - - /** - * When deserializing, we need to know how much we deserialized from the constructor call. - * - * @return The new offset - */ - public int offset() { - return offset; - } + public static PeerAddress decode(final ByteBuf buf) { + final PeerAddressBuilder builder = new PeerAddressBuilder(); + final int header = buf.readUnsignedMedium(); + decodeHeader(builder, header); + + //relays + for(int i=0;i>> 17)}; + builder.ipv4Flag((header & IPV4) == IPV4) + .ipv6Flag((header & IPV6) == IPV6) + .reachable4UDP((header & REACHABLE4_UDP) == REACHABLE4_UDP) + .reachable4TCP((header & REACHABLE4_TCP) == REACHABLE4_TCP) + .reachable4UDT((header & REACHABLE4_UDT) == REACHABLE4_UDT) + .reachable6UDP((header & REACHABLE6_UDP) == REACHABLE6_UDP) + .reachable6TCP((header & REACHABLE6_TCP) == REACHABLE6_TCP) + .reachable6UDT((header & REACHABLE6_UDT) == REACHABLE6_UDT) + .relaySize((header & RELAY_SIZE_MASK) >>> 8) + .holePunching((header & RELAY_FLAGS_MASK) == HOLE_PUNCHING) + .slow((header & RELAY_FLAGS_MASK) == SLOW) + .unreachable((header & UNREACHABLE) == UNREACHABLE) + .net4Internal((header & NET4_INTERNAL) == NET4_INTERNAL) + .skipIPv4((header & SKIP_IPV4) == SKIP_IPV4) + .skipIPv6((header & SKIP_IPV6) == SKIP_IPV6) + .relayTypes(BitSet.valueOf(tmp)); + return builder; + } /** - * @return The size of the serialized peer address + * @return The size of the serialized peer address, calculated using header information only */ public int size() { + int size = HEADER_SIZE + Number160.BYTE_ARRAY_SIZE; + for(int i=0;i 0) { - byte result = (byte) (relaySize << TYPE_BIT_SIZE); - byte types = Utils.createByte(relayType); - result |= (byte) (types & MASK_1F); - return result; - } - return 0; - } @Override public String toString() { StringBuilder sb = new StringBuilder("paddr["); - sb.append(peerId.toString()).append(peerSocketAddress.toString()).append(','); - - if(net6) { - sb.append('6'); + + if(ipv4Flag) { + sb.append(ipv4Socket); + if(!reachable4UDP) { + sb.append("u!"); + } + if(!reachable4TCP) { + sb.append("t!"); + } + if(!reachable4UDT) { + sb.append("d!"); + } } - if(firewalledTCP) { - sb.append('t'); + if(net4Internal) { + sb.append(ipInternalSocket); } - if(firewalledUDP) { - sb.append('u'); + if(ipv6Flag) { + sb.append(ipv6Socket); + if(!reachable6UDP) { + sb.append("u!"); + } + if(!reachable6TCP) { + sb.append("t!"); + } + if(!reachable6UDT) { + sb.append("d!"); + } } - if(relayed) { - sb.append('r'); + sb.append('{'); + if(holePunching) { + sb.append('h'); } if(slow) { sb.append('s'); } - if(portForwarding) { - sb.append('p'); + if(unreachable) { + sb.append('u'); } - if(net4Private) { + if(skipIPv4) { sb.append('4'); } - sb.append(']'); - - if (relayed) { - sb.append("r:(").append(peerSocketAddresses.size()).append(")") - .append(Arrays.toString(peerSocketAddresses.toArray())); + if(skipIPv6) { + sb.append('6'); } - - return sb.toString(); + sb.append('}'); + + sb.append("r:").append(relaySize).append("("); + for(final PeerSocketAddress relay:relays) { + sb.append(relay); + } + sb.append(')'); + + sb.append(peerId); + + return sb.append(']').toString(); } @Override @@ -609,331 +539,28 @@ public int hashCode() { // don't calculate all the time, only once. return this.hashCode; } - - /** - * @return UDP port - */ - public int udpPort() { - return peerSocketAddress.udpPort(); - } - - /** - * @return TCP port - */ - public int tcpPort() { - return peerSocketAddress.tcpPort(); - } - - /** - * @return True if the peer cannot be reached via UDP - */ - public boolean isFirewalledUDP() { - return firewalledUDP; - } - - /** - * @return True if the peer cannot be reached via TCP - */ - public boolean isFirewalledTCP() { - return firewalledTCP; - } - - /** - * @return True if the inet address is IPv6 - */ - public boolean isIPv6() { - return net6; - } - - /** - * @return True if the inet address is IPv4 - */ - public boolean isIPv4() { - return !net6; - } - - /** - * @return If this peer address is used as a relay - */ - public boolean isRelayed() { - return relayed; - } - - /** - * @return if the peer is slow (might be a relayed mobile device) - */ - public boolean isSlow() { - return slow; - } - - public boolean isPortForwarding() { - return portForwarding; - } - - public boolean isNet4Private() { - return net4Private; - } - - /** - * Create a new PeerAddress and change the relayed status. - - * @param isRelayed - * the new relay status - * @return The newly created peer address - */ - public PeerAddress changeRelayed(final boolean isRelayed) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, isRelayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the slow status - - * @param isSlow - * the new status - * @return The newly created peer address - */ - public PeerAddress changeSlow(final boolean isSlow) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, isSlow, portForwarding, net4Private, - peerSocketAddresses); - } - - public PeerAddress changePortForwarding(final boolean portForwarding) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the firewall UDP status. - * - * @param firewalledUDP - * the new status - * @return The newly created peer address - */ - public PeerAddress changeFirewalledUDP(final boolean firewalledUDP) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the firewall TCP status. - * - * @param firewalledTCP - * the new status - * @return The newly created peer address - */ - public PeerAddress changeFirewalledTCP(final boolean firewalledTCP) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the TCP and UDP ports. - * - * @param tcpPort - * The new TCP port - * @param udpPort - * The new UDP port - * @return The newly created peer address - */ - public PeerAddress changePorts(final int tcpPort, final int udpPort) { - return new PeerAddress(peerId, new PeerSocketAddress(peerSocketAddress.inetAddress(), tcpPort, - udpPort), internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the InetAddress. - * - * @param inetAddress - * The new InetAddress - * @return The newly created peer address - */ - public PeerAddress changeAddress(final InetAddress inetAddress) { - return new PeerAddress(peerId, new PeerSocketAddress(inetAddress, peerSocketAddress.tcpPort(), - peerSocketAddress.udpPort()), internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, peerSocketAddresses); - } - - /** - * Create a new PeerAddress and change the peer id. - * - * @param peerId - * the new peer id - * @return The newly created peer address - */ - public PeerAddress changePeerId(final Number160 peerId) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - public PeerAddress changePeerSocketAddresses(Collection peerSocketAddresses) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - - public PeerAddress changePeerSocketAddress(PeerSocketAddress peerSocketAddress) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, net4Private, - peerSocketAddresses); - } - public PeerAddress changeInternalPeerSocketAddress(PeerSocketAddress internalPeerSocketAddress) { - return new PeerAddress(peerId, peerSocketAddress, internalPeerSocketAddress, firewalledTCP, firewalledUDP, relayed, slow, portForwarding, internalPeerSocketAddress!=null, - peerSocketAddresses); - } - - /** - * @return The relay peers - */ - public Collection peerSocketAddresses() { - return peerSocketAddresses; - } - - /** - * Checks if option has IPv6 set. - * - * @param options - * The option field, lowest 8 bit - * @return True if its IPv6 - */ - private static boolean isNet6(final int options) { - return ((options & Utils.MASK_FF) & NET6) > 0; - } - - /** - * Checks if option has firewall TCP set. - * - * @param options - * The option field, lowest 8 bit - * @return True if it firewalled via TCP - */ - private static boolean isFirewalledTCP(final int options) { - return ((options & Utils.MASK_FF) & FIREWALL_TCP) > 0; - } - - /** - * Checks if option has firewall UDP set. - * - * @param options - * The option field, lowest 8 bit - * @return True if it firewalled via UDP - */ - private static boolean isFirewalledUDP(final int options) { - return ((options & Utils.MASK_FF) & FIREWALL_UDP) > 0; - } - - /** - * Checks if option has relay flag set. - * - * @param options - * The option field, lowest 8 bit - * @return True if it is used as a relay - */ - private static boolean isRelay(final int options) { - return ((options & Utils.MASK_FF) & RELAYED) > 0; - } - - /** - * Checks if option has slow flag set - * - * @param options - * The option field - * @return true if the peer is slow - */ - private static boolean isSlow(final int options) { - return ((options & Utils.MASK_FF) & SLOW) > 0; - } - - private static boolean isPortForwarding(final int options) { - return ((options & Utils.MASK_FF) & PORT_FORWARDING) > 0; - } - - private static boolean isNet4Private(final int options) { - return ((options & Utils.MASK_FF) & NET4_PRIVATE) > 0; - } - - /** - * Calculates the size based on the two header bytes. - * - * @param header - * The header in the lower 16 bits of this integer. - * @return the expected size of the peer address - */ - public static int size(final int header) { - int options = (header >>> Utils.BYTE_BITS) & Utils.MASK_FF; - int relays = header & Utils.MASK_FF; - return size(options, relays); - } - - /** - * Calculates the size based on the two header bytes. - * - * @param options - * The option tells us if the inet address is IPv4 or IPv6 - * @param relays - * The relays tells us how many relays we have and of what type they are. - * @return returns the expected size of the peer address - */ - public static int size(final int options, final int relays) { - // header + tcp port + udp port + peer id - int size = HEADER_SIZE + PORTS_SIZE + Number160.BYTE_ARRAY_SIZE; - if (isNet6(options)) { - size += Utils.IPV6_BYTES; - } else if(isNet4Private(options)) { - size += Utils.IPV4_BYTES + Utils.IPV4_BYTES + PORTS_SIZE; - } - else { - size += Utils.IPV4_BYTES; - } - // count the relays - final int relaySize = (relays >>> TYPE_BIT_SIZE) & MASK_07; - final byte b = (byte) (relays & MASK_1F); - final BitSet relayType = Utils.createBitSet(b); - for (int i = 0; i < relaySize; i++) { - size += PORTS_SIZE; - if (relayType.get(i)) { - size += Utils.IPV6_BYTES; - } else { - size += Utils.IPV4_BYTES; - } - } - return size; - } - - public int relaySize() { - return relaySize; - } - - public PeerSocketAddress internalPeerSocketAddress() { - return internalPeerSocketAddress; - } - - public PeerSocketAddress strip() { - if(internalPeerSocketAddress == null) { - throw new IllegalArgumentException("internal peer socket must be set"); - } - if(internalNetworkPrefix == -1) { - return internalPeerSocketAddress; - } - IP.IPv4 masked = IP.fromInet4Address(internalPeerSocketAddress.inetAddress()); - masked = masked.maskWithNetworkMaskInv(internalNetworkPrefix); - final InetAddress inet = masked.toInetAddress(); - return new PeerSocketAddress(inet, internalPeerSocketAddress.tcpPort(), internalPeerSocketAddress.udpPort()); - } - - public InetAddress calcInternalInetAddress(InetAddress remote) { - if(internalNetworkPrefix == -1) { + public IPv4 calcInternalInetAddress(IPv4 remote) { + if(ipInternalNetworkPrefix == -1) { throw new IllegalArgumentException("network prefix must be set"); } - if(internalPeerSocketAddress == null) { + if(ipInternalSocket == null) { throw new IllegalArgumentException("internal peer socket must be set"); } - IP.IPv4 mask = IP.fromInet4Address(internalPeerSocketAddress.inetAddress()); - mask = mask.maskWithNetworkMask(internalNetworkPrefix); - IP.IPv4 masked = IP.fromInet4Address(remote); - masked = masked.maskWithNetworkMaskInv(internalNetworkPrefix); - return mask.set(masked).toInetAddress(); + IP.IPv4 mask = ipInternalSocket.ipv4().maskWithNetworkMask(ipInternalNetworkPrefix); + IP.IPv4 masked = remote.maskWithNetworkMaskInv(ipInternalNetworkPrefix); + return mask.set(masked); + } + + public PeerAddress withIPSocket(PeerSocketAddress ps) { + if(ps instanceof PeerSocket4Address) { + return withIpv4Socket((PeerSocket4Address) ps); + } else { + return withIpv6Socket((PeerSocket6Address) ps); + } } - private int prefix4(InetAddress inetAddress) { + /*private int prefix4(InetAddress inetAddress) { NetworkInterface networkInterface; try { networkInterface = NetworkInterface.getByInetAddress(internalPeerSocketAddress.inetAddress()); @@ -956,5 +583,20 @@ private int prefix4(InetAddress inetAddress) { e.printStackTrace(); return -1; } - } + }*/ + + /*public PeerSocketAddress strip() { + if(internalPeerSocketAddress == null) { + throw new IllegalArgumentException("internal peer socket must be set"); + } + if(internalNetworkPrefix == -1) { + return internalPeerSocketAddress; + } + IP.IPv4 masked = IP.fromInet4Address(internalPeerSocketAddress.inetAddress()); + masked = masked.maskWithNetworkMaskInv(internalNetworkPrefix); + final InetAddress inet = masked.toInetAddress(); + return new PeerSocketAddress(inet, internalPeerSocketAddress.tcpPort(), internalPeerSocketAddress.udpPort()); + }*/ + + } diff --git a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java index 261a1a34a..64c0b1cc5 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java +++ b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java @@ -16,14 +16,12 @@ package net.tomp2p.peers; -import java.net.Inet4Address; -import java.net.Inet6Address; import java.util.Collection; /** - * Filter peers if the IP is the same. TODO: make subnetting configurable, IPv4 - * and IPv6. Being too strict does not mean to harm the network. Other peers - * will have the information about the peer even if you excluded it. + * Filter peers if the IP is the same. Being too strict does not mean to harm + * the network. Other peers will have the information about the peer even if you + * excluded it. * * @author Thomas Bocek * @@ -42,32 +40,28 @@ public PeerIPFilter(int mask4, int mask6) { public boolean rejectPeerMap(final PeerAddress peerAddress, final PeerMap peerMap) { return rejectPreRouting(peerAddress, peerMap.all()); } - + @Override - public boolean rejectPreRouting(PeerAddress peerAddress, Collection all) { - if (peerAddress.inetAddress() instanceof Inet4Address) { - IP.IPv4 ipv4 = IP.fromInet4Address(peerAddress.inetAddress()); - for (PeerAddress inMap : all) { - if (inMap.inetAddress() instanceof Inet4Address) { - IP.IPv4 ipv4Test = IP.fromInet4Address(inMap.inetAddress()); - if (ipv4.maskWithNetworkMask(mask4).equals(ipv4Test.maskWithNetworkMask(mask4))) { - return true; - } - } + public boolean rejectPreRouting(final PeerAddress peerAddress, final Collection all) { + + final IP.IPv4 ipv4 = peerAddress.ipv4Socket().ipv4(); + for (final PeerAddress inMap : all) { + final IP.IPv4 ipv4Test = inMap.ipv4Socket().ipv4(); + if (ipv4.maskWithNetworkMask(mask4).equals(ipv4Test.maskWithNetworkMask(mask4))) { + return true; } - } else { - IP.IPv6 ipv6 = IP.fromInet6Address( peerAddress.inetAddress()); - for (PeerAddress inMap : all) { - if (inMap.inetAddress() instanceof Inet6Address) { - IP.IPv6 ipv6Test = IP.fromInet6Address(inMap.inetAddress()); - if (ipv6.maskWithNetworkMask(mask6).equals(ipv6Test.maskWithNetworkMask(mask6))) { - return true; - } - } + } + + final IP.IPv6 ipv6 = peerAddress.ipv6Socket().ipv6(); + for (final PeerAddress inMap : all) { + final IP.IPv6 ipv6Test = inMap.ipv6Socket().ipv6(); + if (ipv6.maskWithNetworkMask(mask6).equals(ipv6Test.maskWithNetworkMask(mask6))) { + return true; } + } + return false; } - } diff --git a/core/src/main/java/net/tomp2p/peers/PeerMap.java b/core/src/main/java/net/tomp2p/peers/PeerMap.java index 2b10269be..dddca8af3 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerMap.java +++ b/core/src/main/java/net/tomp2p/peers/PeerMap.java @@ -305,21 +305,15 @@ public boolean peerFound(PeerAddress remotePeer, final PeerAddress referrer, fin //if we have first hand information, that means we send a message to that peer and we received a reply. //So its not firewalled. This happens in the discovery phase - if (remotePeer.isFirewalledTCP() || remotePeer.isFirewalledUDP()) { + if (remotePeer.unreachable()) { if(firstHand) { - remotePeer = remotePeer.changeFirewalledTCP(false).changeFirewalledUDP(false); + remotePeer = remotePeer.withUnreachable(false); } else { - LOG.debug("peer is firewalled, reject"); + LOG.debug("peer is unreachable, reject"); return false; } } - //if a peer is relayed but cannot provide any relays, it is useless - if (remotePeer.isRelayed() && remotePeer.peerSocketAddresses().isEmpty()) { - LOG.debug("relayed without any relays, reject"); - return false; - } - final boolean probablyDead = offlineMap.containsKey(remotePeer.peerId()) || shutdownMap.containsKey(remotePeer.peerId()) || exceptionMap.containsKey(remotePeer.peerId()); diff --git a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java index 06e3e76b0..fb381cc53 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java @@ -1,277 +1,334 @@ -/* - * Copyright 2013 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.peers; -import io.netty.buffer.ByteBuf; - -import java.io.Serializable; -import java.net.Inet4Address; -import java.net.InetAddress; import java.net.InetSocketAddress; +import io.netty.buffer.ByteBuf; +import lombok.Builder; +import lombok.Getter; +import lombok.experimental.Accessors; +import lombok.experimental.Wither; +import net.tomp2p.peers.IP.IPv4; +import net.tomp2p.peers.IP.IPv6; +import net.tomp2p.utils.Pair; import net.tomp2p.utils.Utils; -/** - * A PeerSocketAddress includes always both ports, UDP and TCP. - * - * @author Thomas Bocek - * - */ -public class PeerSocketAddress implements Serializable { - private static final long serialVersionUID = 8483270473601620720L; - private final InetAddress inetAddress; - private final int tcpPort; - private final int udpPort; - private final int offset; - - /** - * Creates a PeerSocketAddress including both UDP and TCP ports. - * - * @param inetAddress - * The InetAddress of the peer. Can be IPv4 or IPv6 - * @param tcpPort - * The TCP port - * @param udpPort - * The UDP port - */ - public PeerSocketAddress(final InetAddress inetAddress, final int tcpPort, final int udpPort) { - this(inetAddress, tcpPort, udpPort, -1); - } - - /** - * Creates a PeerSocketAddress including both UDP and TCP ports. - * This constructor is used mostly internally as the offset is stored as well. - * - * @param inetAddress - * The InetAddress of the peer. Can be IPv4 or IPv6 - * @param tcpPort - * The TCP port - * @param udpPort - * The UDP port - * @param offset - * The offset that we processed - */ - public PeerSocketAddress(final InetAddress inetAddress, final int tcpPort, final int udpPort, final int offset) { - this.inetAddress = inetAddress; - this.tcpPort = tcpPort; - this.udpPort = udpPort; - this.offset = offset; - } +public abstract class PeerSocketAddress { + + public final static int PORT_SIZE = 6; + public abstract int size(); + public abstract int encode(final byte[] array, int offset); + public abstract int encode(final byte[] array, int offset, boolean skipAddress); + public abstract PeerSocketAddress encode(final ByteBuf buf); + public abstract PeerSocketAddress encode(final ByteBuf buf, boolean skipAddress); + public abstract String toString(); + + @Builder + @Accessors(fluent = true, chain = true) + public static class PeerSocket4Address extends PeerSocketAddress { + + //ports + ip size + public final static int SIZE = PORT_SIZE + 4; + + @Getter @Wither final private IPv4 ipv4; + @Getter @Wither final private int udpPort; + @Getter @Wither final private int tcpPort; + @Getter @Wither final private int udtPort; + + public static Pair decode(final byte[] array, int offset) { + return decode(array, offset, false); + } + + public static Pair decode(final byte[] array, int offset, final boolean skipAddress) { + PeerSocket4AddressBuilder builder = new PeerSocket4AddressBuilder(); + if(!skipAddress) { + final int ip = Utils.byteArrayToInt(array, offset); + offset +=4; + builder.ipv4(IPv4.fromInt(ip)); + } + final int udpPort = Utils.byteArrayToShort(array, offset); + offset +=2; + final int tcpPort = Utils.byteArrayToShort(array, offset); + offset +=2; + final int udtPort = Utils.byteArrayToShort(array, offset); + offset +=2; + return new Pair ( + builder.udpPort(udpPort) + .tcpPort(tcpPort) + .udtPort(udtPort) + .build(), offset); + } + + public static PeerSocket4Address decode(ByteBuf buf) { + return decode(buf, false); + } + + public static PeerSocket4Address decode(ByteBuf buf, final boolean skipAddress) { + PeerSocket4AddressBuilder builder = new PeerSocket4AddressBuilder(); + if(!skipAddress) { + builder.ipv4(IPv4.fromInt(buf.readInt())); + } + return builder.udpPort(buf.readUnsignedShort()) + .tcpPort(buf.readUnsignedShort()) + .udtPort(buf.readUnsignedShort()) + .build(); + } + + @Override + public int encode(final byte[] array, int offset) { + return encode(array, offset, false); + } + + @Override + public int encode(final byte[] array, int offset, final boolean skipAddress) { + if(!skipAddress) { + offset = Utils.intToByteArray(ipv4.toInt(), array, offset); + } + offset = Utils.shortToByteArray(udpPort, array, offset); + offset = Utils.shortToByteArray(tcpPort, array, offset); + offset = Utils.shortToByteArray(udtPort, array, offset); + return offset; + } + + @Override + public PeerSocket4Address encode(final ByteBuf buf) { + return encode(buf, false); + } + + @Override + public PeerSocket4Address encode(final ByteBuf buf, final boolean skipAddress) { + if(!skipAddress) { + buf.writeInt(ipv4.toInt()); + } + buf.writeShort(udpPort); + buf.writeShort(tcpPort); + buf.writeShort(udtPort); + return this; + } + + public InetSocketAddress createUDPSocket() { + return new InetSocketAddress(ipv4.toInetAddress(), udpPort); + } + + public InetSocketAddress createTCPSocket() { + return new InetSocketAddress(ipv4.toInetAddress(), tcpPort); + } + + public InetSocketAddress createUDTSocket() { + return new InetSocketAddress(ipv4.toInetAddress(), udtPort); + } + + public InetSocketAddress createSocket(int port) { + return new InetSocketAddress(ipv4.toInetAddress(), port); + } - /** - * Converts a byte array into a PeerSocketAddress. - * - * @param me - * The byte array - * @param isIPv4 - * Whether its IPv4 or IPv6 - * @param offsetOriginal - * The offset from where to start reading in the array - * @return the PeerSocketAddress and the new offset - */ - public static PeerSocketAddress create(final byte[] me, final boolean isIPv4, final int offsetOriginal) { - int offset = offsetOriginal; - final int tcpPort = ((me[offset++] & Utils.MASK_FF) << Utils.BYTE_BITS) + (me[offset++] & Utils.MASK_FF); - final int udpPort = ((me[offset++] & Utils.MASK_FF) << Utils.BYTE_BITS) + (me[offset++] & Utils.MASK_FF); + @Override + public int size() { + return SIZE; + } - final InetAddress address; - if (isIPv4) { - address = Utils.inet4FromBytes(me, offset); - offset += Utils.IPV4_BYTES; - } else { - address = Utils.inet6FromBytes(me, offset); - offset += Utils.IPV6_BYTES; + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + return sb.append(ipv4) + .append(":t") + .append(tcpPort) + .append("/u") + .append(udpPort) + .append("/d") + .append(udtPort).toString(); + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof PeerSocket4Address)) { + return false; + } + if (this == obj) { + return true; + } + final PeerSocket4Address psa = (PeerSocket4Address) obj; + return Utils.equals(psa.ipv4, ipv4) + && psa.tcpPort == tcpPort + && psa.udpPort == udpPort + && psa.udtPort == udtPort; } - return new PeerSocketAddress(address, tcpPort, udpPort, offset); - } - - /** - * Decodes a PeerSocketAddress from a Netty buffer. - * - * @param buf - * The Netty buffer - * @param isIPv4 - * Whether the address is IPv4 or IPv6 - * @return the PeerSocketAddress and the new offset - */ - public static PeerSocketAddress create(final ByteBuf buf, final boolean isIPv4) { - final int tcpPort = buf.readUnsignedShort(); - final int udpPort = buf.readUnsignedShort(); - - final InetAddress address; - final byte[] me; - if (isIPv4) { - me = new byte[Utils.IPV4_BYTES]; - buf.readBytes(me); - address = Utils.inet4FromBytes(me, 0); - } else { - me = new byte[Utils.IPV6_BYTES]; - buf.readBytes(me); - address = Utils.inet6FromBytes(me, 0); + + public boolean equalsWithoutPorts(final Object obj) { + if (!(obj instanceof PeerSocket4Address)) { + return false; + } + if (this == obj) { + return true; + } + final PeerSocket4Address psa = (PeerSocket4Address) obj; + return Utils.equals(psa.ipv4, ipv4); + } + + @Override + public int hashCode() { + return Utils.hashCode(ipv4) ^ (tcpPort << 16) ^ udpPort ^ udtPort; } - return new PeerSocketAddress(address, tcpPort, udpPort, buf.readerIndex()); - } - - /** - * Creates the socket address to reach this peer with TCP. - * - * @param peerSocketAddress - * The peer's PeerSocketAddress - * - * @return The socket address to reach this peer with TCP. - */ - public static InetSocketAddress createSocketTCP(PeerSocketAddress peerSocketAddress) { - return new InetSocketAddress(peerSocketAddress.inetAddress(), peerSocketAddress.tcpPort()); - } - /** - * Creates the socket address to reach this peer with UDP. - * - * @param peerSocketAddress - * The peer's PeerSocketAddress - * - * @return The socket address to reach this peer with UDP. - */ - public static InetSocketAddress createSocketUDP(PeerSocketAddress peerSocketAddress) { - return new InetSocketAddress(peerSocketAddress.inetAddress(), peerSocketAddress.udpPort()); + } - - /** - * @return The inernet address, which is IPv4 or IPv6. - */ - public InetAddress inetAddress() { - return inetAddress; - } - - /** - * @return The TCP port. - */ - public int tcpPort() { - return tcpPort; - } - - /** - * @return The UDP port. - */ - public int udpPort() { - return udpPort; - } - - /** - * @return The offset. - */ - public int offset() { - return offset; - } - - /** - * Serializes the PeerSocketAddress to a byte array. First, the ports (TCP, UDP) are serialized, then the address. - * - * @return The serialized PeerSocketAddress - */ - public byte[] toByteArray() { - int size = size(); - byte[] retVal = new byte[size]; - int size2 = toByteArray(retVal, 0); - if(size!=size2) { - throw new RuntimeException("Sizes do not match."); - } - return retVal; - } - - /** - * Serializes the PeerSocketAddress to a byte array. First, the ports (TCP, UDP) are serialized, then the address. - * - * @param me - * The byte array to serialize to - * @param offset - * The offset from where to start - * @return How many data has been written - */ - public int toByteArray(final byte[] me, final int offset) { - int offset2 = offset; - me[offset2++] = (byte) (tcpPort >>> Utils.BYTE_BITS); - me[offset2++] = (byte) tcpPort; - me[offset2++] = (byte) (udpPort >>> Utils.BYTE_BITS); - me[offset2++] = (byte) udpPort; - if (inetAddress instanceof Inet4Address) { - System.arraycopy(inetAddress.getAddress(), 0, me, offset2, Utils.IPV4_BYTES); - offset2 += Utils.IPV4_BYTES; - } else { - System.arraycopy(inetAddress.getAddress(), 0, me, offset2, Utils.IPV6_BYTES); - offset2 += Utils.IPV6_BYTES; + @Builder + @Accessors(fluent = true, chain = true) + public static class PeerSocket6Address extends PeerSocketAddress { + + //ports + ip size + public final static int SIZE = PORT_SIZE + 16; + + @Getter @Wither final private IPv6 ipv6; + @Getter @Wither final private int udpPort; + @Getter @Wither final private int tcpPort; + @Getter @Wither final private int udtPort; + + public static Pair decode(final byte[] array, int offset) { + return decode(array, offset, false); + } + + public static Pair decode(final byte[] array, int offset, final boolean skipAddress) { + PeerSocket6AddressBuilder builder = new PeerSocket6AddressBuilder(); + if(!skipAddress) { + final long hi = Utils.byteArrayToLong(array, offset); + offset +=8; + final long lo = Utils.byteArrayToLong(array, offset); + offset +=8; + builder.ipv6(IPv6.fromLong(hi, lo)); + } + final int udpPort = Utils.byteArrayToShort(array, offset); + offset +=2; + final int tcpPort = Utils.byteArrayToShort(array, offset); + offset +=2; + final int udtPort = Utils.byteArrayToShort(array, offset); + offset +=2; + return new Pair ( + builder.udpPort(udpPort) + .tcpPort(tcpPort) + .udtPort(udtPort) + .build(), offset); + } + + public static PeerSocket6Address decode(ByteBuf buf) { + return decode(buf, false); + } + + public static PeerSocket6Address decode(ByteBuf buf, final boolean skipAddress) { + PeerSocket6AddressBuilder builder = new PeerSocket6AddressBuilder(); + if(!skipAddress) { + builder.ipv6(IPv6.fromLong(buf.readLong(),buf.readLong())); + } + return builder.udpPort(buf.readUnsignedShort()) + .tcpPort(buf.readUnsignedShort()) + .udtPort(buf.readUnsignedShort()) + .build(); + } + + @Override + public int encode(final byte[] array, int offset) { + return encode(array, offset, false); + } + + @Override + public int encode(final byte[] array, int offset, final boolean skipAddress) { + if(!skipAddress) { + offset = Utils.longToByteArray(ipv6.toLongHi(), ipv6.toLongLo(), array, offset); + } + offset = Utils.shortToByteArray(udpPort, array, offset); + offset = Utils.shortToByteArray(tcpPort, array, offset); + offset = Utils.shortToByteArray(udtPort, array, offset); + return offset; + } + + @Override + public PeerSocket6Address encode(final ByteBuf buf) { + return encode(buf, false); + } + + @Override + public PeerSocket6Address encode(final ByteBuf buf, final boolean skipAddress) { + if(!skipAddress) { + buf.writeLong(ipv6.toLongHi()); + buf.writeLong(ipv6.toLongLo()); + } + buf.writeShort(udpPort); + buf.writeShort(tcpPort); + buf.writeShort(udtPort); + return this; + } + + public InetSocketAddress createUDPSocket() { + return new InetSocketAddress(ipv6.toInetAddress(), udpPort); + } + + public InetSocketAddress createTCPSocket() { + return new InetSocketAddress(ipv6.toInetAddress(), tcpPort); + } + + public InetSocketAddress createUDTSocket() { + return new InetSocketAddress(ipv6.toInetAddress(), udtPort); + } + + public InetSocketAddress createSocket(int port) { + return new InetSocketAddress(ipv6.toInetAddress(), port); + } + + @Override + public int size() { + return SIZE; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + return sb.append(ipv6) + .append(":t") + .append(tcpPort) + .append("/u") + .append(udpPort) + .append("/d") + .append(udtPort).toString(); + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof PeerSocket6Address)) { + return false; + } + if (this == obj) { + return true; + } + final PeerSocket6Address psa = (PeerSocket6Address) obj; + return Utils.equals(psa.ipv6, ipv6) + && psa.tcpPort == tcpPort + && psa.udpPort == udpPort + && psa.udtPort == udtPort; + } + + public boolean equalsWithoutPorts(final Object obj) { + if (!(obj instanceof PeerSocket6Address)) { + return false; + } + if (this == obj) { + return true; + } + final PeerSocket6Address psa = (PeerSocket6Address) obj; + return Utils.equals(psa.ipv6, ipv6); + } + + @Override + public int hashCode() { + return Utils.hashCode(ipv6) ^ (tcpPort << 16) ^ udpPort ^ udtPort; } - return offset2; } - /** - * Calculates the size of this PeerSocketAddress in bytes. - * Format: 2 bytes TCP port, 2 bytes UDP port, 4/16 bytes IPv4/IPv6 address. - * - * @return The size of this PeerSocketAddress in bytes. - */ - public int size() { - return size(isIPv4()); - } - - /** - * Calculates the size of a PeerSocketAddress in bytes. - * Format: 2 bytes TCP port, 2 bytes UDP port, 4/16 bytes IPv4/IPv6 address. - * - * @param isIPv4 - * Whether the address is IPv4 or IPv6. - * - * @return The size of this PeerSocketAddress in bytes. - */ - public static int size(boolean isIPv4) { - return 2 + 2 + (isIPv4 ? Utils.IPV4_BYTES:Utils.IPV6_BYTES); - } - - public boolean isIPv4() { - return inetAddress instanceof Inet4Address; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(inetAddress); - if(tcpPort == udpPort) { - sb.append(",").append(tcpPort); - } else { - sb.append(",t:").append(tcpPort).append(",u:").append(udpPort); - } - return sb.toString(); - } - - @Override - public boolean equals(final Object obj) { - if (!(obj instanceof PeerSocketAddress)) { - return false; - } - if (this == obj) { - return true; - } - PeerSocketAddress psa = (PeerSocketAddress) obj; - return psa.inetAddress.equals(inetAddress) && psa.tcpPort == tcpPort && psa.udpPort == udpPort; - } - - @Override - public int hashCode() { - return inetAddress.hashCode() ^ tcpPort ^ udpPort; - } + public InetSocketAddress createTCPSocket() { + if(this instanceof PeerSocket4Address) { + return ((PeerSocket4Address)this).createTCPSocket(); + } else { + return ((PeerSocket6Address)this).createTCPSocket(); + } + + } } diff --git a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java index e13ad1aae..623e2f0a3 100644 --- a/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java +++ b/core/src/main/java/net/tomp2p/rpc/DispatchHandler.java @@ -155,7 +155,7 @@ public void forwardMessage(final Message requestMessage, PeerConnection peerConn // we can contact the peer with its address. The peer may be behind a NAT. //TODO: figure out how to include this. The only thing we currently missing are the ports - if(requestMessage.sender().isNet4Private() || + if(requestMessage.sender().net4Internal() || (requestMessage.type() == Type.REQUEST_1 && requestMessage.command() == RPC.Commands.RELAY.getNr()) || (requestMessage.type() == Type.REQUEST_2 && requestMessage.command() == RPC.Commands.PING.getNr()) ) { //request 2/ping is a ping discover, where we don't know our external address and port. Don't add this! diff --git a/core/src/main/java/net/tomp2p/rpc/PingRPC.java b/core/src/main/java/net/tomp2p/rpc/PingRPC.java index 0e9e7a347..5671dcec1 100644 --- a/core/src/main/java/net/tomp2p/rpc/PingRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/PingRPC.java @@ -315,11 +315,6 @@ public void handleResponse(final Message message, PeerConnection peerConnection, if(message.isSendSelf()) { responseMessage = createResponseMessage(message, Type.NOT_FOUND); LOG.warn("Sending probe ping request to yourself? If those are two different peers, messages may be dropped"); - if(!message.sender().inetAddress().equals(message.recipient().inetAddress())) { - if(message.sender().peerId().equals(message.recipient().peerId())) { - LOG.warn("You seem to use the same peerId for different peers. This may result in dropped messages"); - } - } } else { responseMessage = createResponseMessage(message, Type.OK); @@ -404,7 +399,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio PeerAddress serverAddress = peerBean().serverPeerAddress(); if (message.isUdp()) { // UDP - PeerAddress newServerAddress = serverAddress.changeFirewalledUDP(false); + PeerAddress newServerAddress = serverAddress.withReachable4UDP(true); peerBean().serverPeerAddress(newServerAddress); synchronized (reachableListeners) { for (PeerReachable listener : reachableListeners) { @@ -414,7 +409,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio responseMessage = message; } else { // TCP - PeerAddress newServerAddress = serverAddress.changeFirewalledTCP(false); + PeerAddress newServerAddress = serverAddress.withReachable4TCP(true); peerBean().serverPeerAddress(newServerAddress); synchronized (reachableListeners) { for (PeerReachable listener : reachableListeners) { diff --git a/core/src/main/java/net/tomp2p/rpc/SimpleBloomFilter.java b/core/src/main/java/net/tomp2p/rpc/SimpleBloomFilter.java index 61594c134..bf7d657aa 100644 --- a/core/src/main/java/net/tomp2p/rpc/SimpleBloomFilter.java +++ b/core/src/main/java/net/tomp2p/rpc/SimpleBloomFilter.java @@ -361,7 +361,7 @@ public BitSet getBitSet() { * @param buf * The byte buffer where the bloom filter will be written. */ - public void toByteBuf(final ByteBuf buf) { + public void encode(final ByteBuf buf) { buf.writeShort(byteArraySize + SIZE_HEADER_ELEMENTS + SIZE_HEADER_LENGTH); buf.writeInt(expectedElements); byte[] tmp = RPCUtils.toByteArray(bitSet); diff --git a/core/src/main/java/net/tomp2p/utils/Utils.java b/core/src/main/java/net/tomp2p/utils/Utils.java index cfd8848b2..73e607d31 100644 --- a/core/src/main/java/net/tomp2p/utils/Utils.java +++ b/core/src/main/java/net/tomp2p/utils/Utils.java @@ -15,8 +15,6 @@ */ package net.tomp2p.utils; -import io.netty.buffer.ByteBuf; - import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -55,17 +53,20 @@ import java.util.zip.Deflater; import java.util.zip.Inflater; +import io.netty.buffer.ByteBuf; import net.tomp2p.connection.ChannelCreator; import net.tomp2p.futures.BaseFuture; import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; import net.tomp2p.message.Message; import net.tomp2p.message.TrackerData; +import net.tomp2p.peers.IP.IPv4; import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number480; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.storage.DataBuffer; /** @@ -428,10 +429,80 @@ public static void bestEffortclose(Closeable... closables) { public static final byte[] intToByteArray(int value) { return new byte[] { (byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value }; } + + public static final byte[] mediumToByteArray(int value) { + return new byte[] { (byte) (byte) (value >>> 16), (byte) (value >>> 8), (byte) value }; + } + + public static final int shortToByteArray(int value, byte[] array, int offset) { + array[offset++] = (byte) (value >>> 8); + array[offset++] = (byte) value; + return offset; + } + + public static final int mediumToByteArray(int value, byte[] array, int offset) { + array[offset++] = (byte) (value >>> 16); + array[offset++] = (byte) (value >>> 8); + array[offset++] = (byte) value; + return offset; + } + + public static final int intToByteArray(int value, byte[] array, int offset) { + array[offset++] = (byte) (value >>> 24); + array[offset++] = (byte) (value >>> 16); + array[offset++] = (byte) (value >>> 8); + array[offset++] = (byte) value; + return offset; + } + + public static int longToByteArray(long longHi, long longLo, byte[] array, int offset) { + array[offset++] = (byte) (longHi >>> 56); + array[offset++] = (byte) (longHi >>> 48); + array[offset++] = (byte) (longHi >>> 40); + array[offset++] = (byte) (longHi >>> 32); + array[offset++] = (byte) (longHi >>> 24); + array[offset++] = (byte) (longHi >>> 16); + array[offset++] = (byte) (longHi >>> 8); + array[offset++] = (byte) longHi; + + array[offset++] = (byte) (longLo >>> 56); + array[offset++] = (byte) (longLo >>> 48); + array[offset++] = (byte) (longLo >>> 40); + array[offset++] = (byte) (longLo >>> 32); + array[offset++] = (byte) (longLo >>> 24); + array[offset++] = (byte) (longLo >>> 16); + array[offset++] = (byte) (longLo >>> 8); + array[offset++] = (byte) longLo; + + return offset; + } public static final int byteArrayToInt(byte[] b) { return (b[0] << 24) + ((b[1] & 0xFF) << 16) + ((b[2] & 0xFF) << 8) + (b[3] & 0xFF); } + + public static final int byteArrayToShort(byte[] b, int offset) { + return ((b[offset] & 0xFF) << 8) + (b[offset + 1] & 0xFF); + } + + public static final int byteArrayToMedium(byte[] b, int offset) { + return ((b[offset] & 0xFF) << 16) + ((b[offset + 1] & 0xFF) << 8) + (b[offset + 2] & 0xFF); + } + + public static final int byteArrayToInt(byte[] b, int offset) { + return ((b[offset] & 0xFF) << 24) + ((b[offset + 1] & 0xFF) << 16) + ((b[offset + 2] & 0xFF) << 8) + (b[offset + 3] & 0xFF); + } + + public static long byteArrayToLong(byte[] b, int offset) { + return (((long)b[offset ] & 0xFFl) << 56) | + (((long)b[offset + 1] & 0xFFl) << 48) | + (((long)b[offset + 2] & 0xFFl) << 40) | + (((long)b[offset + 3] & 0xFFl) << 32) | + (((long)b[offset + 4] & 0xFFl) << 24) | + (((long)b[offset + 5] & 0xFFl) << 16) | + (((long)b[offset + 6] & 0xFFl) << 8) | + ( (long)b[offset + 7] & 0xFFl); + } /** * Returns a random element from a collection. This method is pretty slow O(n), but the Java collection @@ -938,18 +1009,24 @@ public static int randomPositiveInt(int upperBound) { return randomInt; } - public static boolean canReflect(PeerAddress recipient, PeerAddress self) { - return recipient.inetAddress().equals(self.inetAddress()) - && self.internalPeerSocketAddress() != null - && recipient.internalPeerSocketAddress()!=null; + public static boolean canReflect(final PeerAddress recipient, final PeerAddress self) { + return recipient.ipv4Socket().ipv4().equals(self.ipv4Socket().ipv4()) + && self.ipInternalSocket() != null + && recipient.ipInternalSocket()!=null; } - public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress self) { + + public static PeerSocket4Address natReflection(final PeerAddress recipient, final PeerAddress self) { //check for NAT reflection if(canReflect(recipient, self)) { //the recipient and me have the same external IP, this means we either send it to us, or to a peer in our network. Since NAT reflection is rarly properly implemented in routers, we need to change the IP address here in order to reach the peer. - InetAddress a = self.calcInternalInetAddress(recipient.internalPeerSocketAddress().inetAddress()); - return new PeerSocketAddress(a, recipient.internalPeerSocketAddress().tcpPort(), recipient.internalPeerSocketAddress().udpPort()); + IPv4 a = self.calcInternalInetAddress(recipient.ipInternalSocket().ipv4()); + + return PeerSocket4Address.builder().ipv4(a) + .udpPort(recipient.ipInternalSocket().udpPort()) + .tcpPort(recipient.ipInternalSocket().tcpPort()) + .udtPort(recipient.ipInternalSocket().udtPort()) + .build(); } return null; } @@ -962,7 +1039,7 @@ public static PeerSocketAddress natReflection(PeerAddress recipient, PeerAddress * @return socketAddress */ public static PeerSocketAddress extractRandomRelay(final Message message) { - Object[] relayInetAddresses = message.recipient().peerSocketAddresses().toArray(); + Object[] relayInetAddresses = message.recipient().relays().toArray(); PeerSocketAddress socketAddress = null; if (relayInetAddresses.length > 0) { // we should be fair and choose one of the relays randomly @@ -973,6 +1050,17 @@ public static PeerSocketAddress extractRandomRelay(final Message message) { } return socketAddress; } + + public static int hashCode(Object obj) { + if(obj == null) { + return 0; + } + return obj.hashCode(); + } + + + + } diff --git a/core/src/test/java/net/tomp2p/Utils2.java b/core/src/test/java/net/tomp2p/Utils2.java index c2aad8202..7da8011bb 100644 --- a/core/src/test/java/net/tomp2p/Utils2.java +++ b/core/src/test/java/net/tomp2p/Utils2.java @@ -20,9 +20,12 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.NavigableSet; import java.util.Random; @@ -36,11 +39,15 @@ import net.tomp2p.p2p.AutomaticFuture; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerBuilder; +import net.tomp2p.peers.IP.IPv4; +import net.tomp2p.peers.IP.IPv6; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.peers.PeerStatistic; public class Utils2 { @@ -100,13 +107,13 @@ public static PeerAddress createAddress(String id) throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); - return n1; + return createPeerAddress(idSender, inetSend, tcpPortSender, udpPortSender); + } - public static PeerStatistic createStatistic(int id) throws UnknownHostException { + + + public static PeerStatistic createStatistic(int id) throws UnknownHostException { return new PeerStatistic(createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false)); } @@ -350,7 +357,62 @@ public static PeerAddress[] createDummyAddress(int size, int portTCP, int portUD public static PeerAddress createAddress(int iid, int portTCP, int portUDP) throws UnknownHostException { Number160 id = new Number160(iid); InetAddress address = InetAddress.getByName("127.0.0.1"); - return new PeerAddress(id, address, portTCP, portUDP); + return createPeerAddress(id, address, portTCP, portUDP); } + public static PeerAddress createPeerAddress(Number160 id, InetAddress address, int portTCP, int portUDP) { + if(address instanceof Inet4Address) { + return PeerAddress.builder().peerId(id).ipv4Socket((PeerSocket4Address)creatPeerSocket(address, portTCP, portUDP)).build(); + } else { + return PeerAddress.builder().peerId(id).ipv6Socket((PeerSocket6Address)creatPeerSocket(address, portTCP, portUDP)).build(); + } + } + + public static PeerSocketAddress creatPeerSocket(InetAddress localHost, int tcp, int udp) { + if(localHost instanceof Inet4Address) { + return PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(localHost)).tcpPort(tcp).udpPort(udp).build(); + } else { + return PeerSocket6Address.builder().ipv6(IPv6.fromInet6Address(localHost)).tcpPort(tcp).udpPort(udp).build(); + } + + } + + public static PeerSocket4Address creatPeerSocket4(Inet4Address localHost, int tcp, int udp) { + return PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(localHost)).tcpPort(tcp).udpPort(udp).build(); + } + + public static PeerAddress createPeerAddress(Number160 id, InetAddress address, int portTCP, int portUDP, + Collection psa) { + if(address instanceof Inet4Address) { + return PeerAddress.builder() + .peerId(id) + .ipv4Socket((PeerSocket4Address)creatPeerSocket(address, portTCP, portUDP)) + .relay(psa) + .build(); + } else { + return PeerAddress.builder() + .peerId(id) + .ipv6Socket((PeerSocket6Address)creatPeerSocket(address, portTCP, portUDP)) + .relay(psa) + .build(); + } + } + + public static PeerAddress createPeerAddress(Number160 id, Inet6Address address, int portTCP, int portUDP, + Collection psa, PeerSocket4Address creatPeerSocket, PeerSocket4Address creatPeerSocket2) { + + return PeerAddress.builder() + .peerId(id) + .ipv6Socket((PeerSocket6Address)creatPeerSocket(address, portTCP, portUDP)) + .relay(psa) + .ipv4Socket(creatPeerSocket) + .ipInternalSocket(creatPeerSocket2) + .build(); + + } + + + + + } diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index c5bd7b99e..bca67e1e9 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -54,7 +54,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.storage.AlternativeCompositeByteBuf; import net.tomp2p.storage.Data; import net.tomp2p.utils.Utils; @@ -456,7 +456,7 @@ public void serializationTest() throws IOException, ClassNotFoundException, m1.buffer(new Buffer(Unpooled.buffer())); Encoder e = new Encoder(null); AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); - e.write(buf, m1, null); + e.write(buf, m1, null, true); Decoder d = new Decoder(null); boolean header = d.decodeHeader(buf, new InetSocketAddress(0), new InetSocketAddress(0)); @@ -485,9 +485,10 @@ public void serializationTestFail() throws IOException, public void testRelayAddresses1() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); m1.type(Message.Type.NOT_FOUND); - List tmp = new ArrayList(); - tmp.add(new PeerSocketAddress(InetAddress.getLocalHost(), 15, 17)); - tmp.add(new PeerSocketAddress(InetAddress.getByName("0:0:0:0:0:0:0:1"), 16, 18)); + List tmp = new ArrayList(); + + tmp.add(Utils2.creatPeerSocket(InetAddress.getLocalHost(), 15, 17)); + tmp.add(Utils2.creatPeerSocket(InetAddress.getByName("0:0:0:0:0:0:0:1"), 16, 18)); m1.peerSocketAddresses(tmp); Message m2 = encodeDecode(m1); Assert.assertEquals(tmp, m2.peerSocketAddresses()); @@ -496,20 +497,21 @@ public void testRelayAddresses1() throws Exception { // encode @Test public void testRelay() throws Exception { - Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), + Collection psa = new ArrayList(); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, false, false, - psa); + PeerSocketAddress2 psaa = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa, psa); + + Message m1 = Utils2.createDummyMessage(); Collection tmp = new ArrayList(); @@ -517,27 +519,26 @@ public void testRelay() throws Exception { m1.neighborsSet(new NeighborSet(-1, tmp)); Message m2 = encodeDecode(m1); - Assert.assertArrayEquals(psa.toArray(), m2.neighborsSet(0).neighbors().iterator().next().peerSocketAddresses().toArray()); + Assert.assertArrayEquals(psa.toArray(), m2.neighborsSet(0).neighbors().iterator().next().relays().toArray()); compareMessage(m1, m2); } @Test public void testRelay2() throws Exception { - Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), + Collection psa = new ArrayList(); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, true, false, - psa); + PeerSocketAddress2 psaa = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa, psa); Message m1 = Utils2.createDummyMessage(); Collection tmp = new ArrayList(); @@ -552,21 +553,22 @@ public void testRelay2() throws Exception { @Test public void testInternalPeerSocket() throws Exception { - Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), + Collection psa = new ArrayList(); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), new PeerSocketAddress( - InetAddress.getByName("0.0.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), true, true, true, true, true, true, - psa); + + PeerSocketAddress2 psaa1 = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + PeerSocketAddress2 psaa2 = Utils2.creatPeerSocket(InetAddress.getByName("0.0.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa1, psaa2, psa); + Message m1 = Utils2.createDummyMessage(); Collection tmp = new ArrayList(); @@ -579,23 +581,14 @@ public void testInternalPeerSocket() throws Exception { } - @Test - public void testRelayFlag() throws Exception { // encode - Message m1 = Utils2.createDummyMessage(); - m1.sender(m1.sender().changeRelayed(true)); - - Message m2 = encodeDecode(m1); - Assert.assertEquals(m1.sender().isRelayed(), m2.sender().isRelayed()); - compareMessage(m1, m2); - } @Test public void testSlowFlag() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); - m1.sender(m1.sender().changeSlow(true)); + m1.sender(m1.sender().withSlow(true)); Message m2 = encodeDecode(m1); - Assert.assertEquals(m1.sender().isSlow(), m2.sender().isSlow()); + Assert.assertEquals(m1.sender().slow(), m2.sender().slow()); compareMessage(m1, m2); } @@ -635,11 +628,11 @@ private Message encodeDecode(final Message m1) throws Exception { AtomicReference m2 = new AtomicReference(); final AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); Encoder encoder = new Encoder(new DSASignatureFactory()); - encoder.write(buf, m1, null); + encoder.write(buf, m1, null, false); ChannelHandlerContext ctx = mockChannelHandlerContext(buf, m2); Decoder decoder = new Decoder(new DSASignatureFactory()); - decoder.decode(ctx, buf, m1.recipient().createSocketTCP(), m1 - .sender().createSocketTCP()); + decoder.decode(ctx, buf, m1.recipient().createSocket4TCP(), m1 + .sender().createSocket4TCP()); buf.release(); return decoder.message(); } @@ -712,11 +705,11 @@ private void compareMessage(final Message m1, final Message m2) { Assert.assertEquals(m1.version(), m2.version()); Assert.assertEquals(m1.command(), m2.command()); compareContentTypes(m1, m2); - Assert.assertEquals(m1.recipient(), m2.recipient()); + Assert.assertEquals(m1.type(), m2.type()); - Assert.assertEquals(m1.sender(), m2.sender()); - Assert.assertEquals(m1.sender().tcpPort(), m2.sender().tcpPort()); - + comparePeerAddresses(m1.sender(), m2.sender(), true); + comparePeerAddresses(m1.recipient(), m2.recipient(), false); + Assert.assertEquals(true, Utils.isSameSets(m1.bloomFilterList(), m2.bloomFilterList())); Assert.assertEquals(true, Utils.isSameSets(m1.bufferList(), m2.bufferList())); @@ -739,11 +732,29 @@ private void compareMessage(final Message m1, final Message m2) { Assert.assertEquals(true, Utils.isSameSets(iter1.next().neighbors(), iter2.next().neighbors())); } - Assert.assertEquals(m1.sender().isFirewalledTCP(), m2.sender().isFirewalledTCP()); - Assert.assertEquals(m1.sender().isFirewalledUDP(), m2.sender().isFirewalledUDP()); - Assert.assertEquals(m1.sender().isRelayed(), m2.sender().isRelayed()); - Assert.assertEquals(m1.sender().isSlow(), m2.sender().isSlow()); - Assert.assertEquals(m1.sender().isPortForwarding(), m2.sender().isPortForwarding()); + + } + + private void comparePeerAddresses(final PeerAddress p1, final PeerAddress p2, boolean isSender) { + + Assert.assertEquals(p1.peerId(), p2.peerId()); + + if(isSender) { + Assert.assertEquals(p1.peerSocketAddress(), p2.peerSocketAddress()); + Assert.assertEquals(p1.unreachable(), p2.unreachable()); + Assert.assertEquals(p1.relays(), p2.relays()); + Assert.assertEquals(p1.relaySize(), p2.relaySize()); + Assert.assertEquals(p1.slow(), p2.slow()); + Assert.assertEquals(p1.holePunching(), p2.holePunching()); + + //tests are currently only IPv4 + Assert.assertEquals(p1.peerSocketAddress().ipv6Flag(), p2.peerSocketAddress().ipv6Flag()); + + Assert.assertEquals(p1.peerSocketAddress().net4Internal(), p1.peerSocketAddress().net4Internal()); + Assert.assertEquals(p1.peerSocketAddress().reachableTCP(), p1.peerSocketAddress().reachableTCP()); + Assert.assertEquals(p1.peerSocketAddress().reachableUDP(), p1.peerSocketAddress().reachableUDP()); + Assert.assertEquals(p1.peerSocketAddress().reachableUDT(), p1.peerSocketAddress().reachableUDT()); + } } /** diff --git a/core/src/test/java/net/tomp2p/peers/TestIP.java b/core/src/test/java/net/tomp2p/peers/TestIP.java index 372466078..5bbb40d68 100644 --- a/core/src/test/java/net/tomp2p/peers/TestIP.java +++ b/core/src/test/java/net/tomp2p/peers/TestIP.java @@ -8,8 +8,6 @@ import org.junit.Assert; import org.junit.Test; -import net.tomp2p.utils.Utils; - public class TestIP { @Test public void testMask4() throws UnknownHostException { diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java index aff2a7c20..81b935909 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java @@ -16,11 +16,12 @@ package net.tomp2p.peers; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.Random; import org.junit.Assert; @@ -30,6 +31,10 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; +import net.tomp2p.Utils2; +import net.tomp2p.utils.Pair; +import net.tomp2p.utils.Utils; + /** * Test the serialization and deserialization of PeerAddress. * @@ -47,6 +52,30 @@ protected void starting(Description description) { System.out.println("Starting test: " + description.getMethodName()); } }; + + @Test + public void testLongConversion() throws UnknownHostException { + long hi = 0x1122334455667788l; + long lo = 0x8877665544332211l; + byte[] me = new byte[16]; + Utils.longToByteArray(hi, lo, me, 0); + + long hi2 = Utils.byteArrayToLong(me, 0); + long lo2 = Utils.byteArrayToLong(me, 8); + + Assert.assertEquals(hi, hi2); + Assert.assertEquals(lo, lo2); + } + + @Test + public void testIPv6Coding() throws UnknownHostException { + PeerAddress pa = Utils2.createPeerAddress(new Number160("0x857e35a42e4677675644522456"), + InetAddress.getByName("0123:4567:89ab:cdef:1111:2222:3333:4444"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16)); + byte[] me = pa.encode(); + PeerAddress pa2 = PeerAddress.decode(me).element0(); + compare(pa, pa2); + } /** * Test serialization and deserialization of PeerAddress. @@ -59,9 +88,9 @@ public void testPeerAddress() throws UnknownHostException { InetAddress address = InetAddress.getByName("127.0.0.1"); int portTCP = RND.nextInt(BIT_16); int portUDP = RND.nextInt(BIT_16); - PeerAddress pa = new PeerAddress(id, address, portTCP, portUDP); - byte[] me = pa.toByteArray(); - PeerAddress pa2 = new PeerAddress(me); + PeerAddress pa = Utils2.createPeerAddress(id, address, portTCP, portUDP); + byte[] me = pa.encode(); + PeerAddress pa2 = PeerAddress.decode(me).element0(); compare(pa, pa2); } @@ -76,9 +105,9 @@ public void testPeerAddress2() throws UnknownHostException { InetAddress address = InetAddress.getByName("192.168.240.230"); int portTCP = RND.nextInt(BIT_16); int portUDP = RND.nextInt(BIT_16); - PeerAddress pa = new PeerAddress(id, address, portTCP, portUDP); - byte[] me = pa.toByteArray(); - PeerAddress pa2 = new PeerAddress(me); + PeerAddress pa = Utils2.createPeerAddress(id, address, portTCP, portUDP); + byte[] me = pa.encode(); + PeerAddress pa2 = PeerAddress.decode(me).element0(); compare(pa, pa2); } @@ -89,19 +118,20 @@ public void testPeerAddress2() throws UnknownHostException { */ @Test public void testPeerAddress3() throws UnknownHostException { - PeerAddress pa1 = new PeerAddress(new Number160("0x857e35a42e444522456"), + PeerAddress pa1 = Utils2.createPeerAddress(new Number160("0x857e35a42e444522456"), InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerAddress pa2 = new PeerAddress(new Number160("0x657435a424444522456"), + PeerAddress pa2 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), InetAddress.getByName("192.168.240.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); final int length = 200; byte[] me = new byte[length]; final int offset = 50; - int offset2 = pa1.toByteArray(me, offset); - pa2.toByteArray(me, offset2); + int offset2 = pa1.encode(me, offset); + pa2.encode(me, offset2); // - PeerAddress pa3 = new PeerAddress(me, offset); - int offset4 = pa3.offset(); - PeerAddress pa4 = new PeerAddress(me, offset4); + Pair pair = PeerAddress.decode(me, offset); + PeerAddress pa3 = pair.element0(); + int offset4 = pair.element1(); + PeerAddress pa4 = PeerAddress.decode(me, offset4).element0(); compare(pa1, pa3); compare(pa2, pa4); } @@ -113,22 +143,23 @@ public void testPeerAddress3() throws UnknownHostException { */ @Test public void testPeerAddress4() throws UnknownHostException { - PeerAddress pa1 = new PeerAddress(new Number160("0x857e35a42e444522456"), + PeerAddress pa1 = Utils2.createPeerAddress(new Number160("0x857e35a42e444522456"), InetAddress.getByName("0123:4567:89ab:cdef:0123:4567:89ab:cdef"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerAddress pa2 = new PeerAddress(new Number160("0x657435a424444522456"), - InetAddress.getByName("0123:4567:89ab:cdef:0123:4567:89ab:cdef"), RND.nextInt(BIT_16), + PeerAddress pa2 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), + InetAddress.getByName("f123:4567:89ab:cdef:0123:4567:89ab:cdef"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); final int length = 200; byte[] me = new byte[length]; final int offset = 50; - int offset2 = pa1.toByteArray(me, offset); - pa2.toByteArray(me, offset2); + int offset2 = pa1.encode(me, offset); + pa2.encode(me, offset2); // - PeerAddress pa3 = new PeerAddress(me, offset); - int offset4 = pa3.offset(); - PeerAddress pa4 = new PeerAddress(me, offset4); + Pair pair = PeerAddress.decode(me, offset); + PeerAddress pa3 = pair.element0(); + int offset4 = pair.element1(); + PeerAddress pa4 = PeerAddress.decode(me, offset4).element0(); compare(pa1, pa3); compare(pa2, pa4); } @@ -142,25 +173,26 @@ public void testPeerAddress4() throws UnknownHostException { public void testPeerAddress5() throws UnknownHostException { Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.231"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)), null, true, true, true, true, true, - false, psa); + + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), + InetAddress.getByName("f123:4567:89ab:cdef:0123:4567:89ab:cdef"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16), psa); final int length = 200; byte[] me = new byte[length]; final int offset = 50; - pa3.toByteArray(me, offset); - PeerAddress pa4 = new PeerAddress(me, offset); + pa3.encode(me, offset); + PeerAddress pa4 = PeerAddress.decode(me, offset).element0(); compare(pa3, pa4); } @@ -174,55 +206,40 @@ public void testPeerAddress5() throws UnknownHostException { public void testPeerAddress6() throws UnknownHostException { Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde1"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde1"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("3123:4567:89ab:cdef:0123:4567:89ab:cde3"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("3123:4567:89ab:cdef:0123:4567:89ab:cde3"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("5123:4567:89ab:cdef:0123:4567:89ab:cde5"), + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("5123:4567:89ab:cdef:0123:4567:89ab:cde5"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde0"), RND.nextInt(BIT_16), - RND.nextInt(BIT_16)), null, true, true, true, true, true, false, psa); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("6123:4567:89ab:cdef:0123:4567:89ab:cde5"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("7123:4567:89ab:cdef:0123:4567:89ab:cde5"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), + (Inet6Address)Inet6Address.getByName("f123:4567:89ab:cdef:0123:4567:89ab:cdef"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16), psa, Utils2.creatPeerSocket4((Inet4Address)Inet4Address.getByName("192.168.230.231"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16)), Utils2.creatPeerSocket4((Inet4Address)Inet4Address.getByName("192.168.230.231"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); - final int length = 200; + final int length = 400; byte[] me = new byte[length]; final int offset = 50; - int offset2 = pa3.toByteArray(me, offset); + int offset2 = pa3.encode(me, offset); int len = offset2 - offset; // 142 is the - Assert.assertEquals(PeerAddress.MAX_SIZE, PeerAddress.size(pa3.options(), pa3.relays())); + Assert.assertEquals(PeerAddress.MAX_SIZE, PeerAddress.size(Utils.byteArrayToMedium(me, offset))); Assert.assertEquals(PeerAddress.MAX_SIZE, len); // - PeerAddress pa4 = new PeerAddress(me, offset); + PeerAddress pa4 = PeerAddress.decode(me, offset).element0(); compare(pa3, pa4); } - - @Test - public void testPeerAddress7() throws UnknownHostException { - - Collection psa = new ArrayList(); - psa.add(new PeerSocketAddress(InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde1"), - RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), - RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("3123:4567:89ab:cdef:0123:4567:89ab:cde3"), - RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("4123:4567:89ab:cdef:0123:4567:89ab:cde4"), - RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - psa.add(new PeerSocketAddress(InetAddress.getByName("5123:4567:89ab:cdef:0123:4567:89ab:cde5"), - RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerAddress pa3 = new PeerAddress(new Number160("0x657435a424444522456"), new PeerSocketAddress( - InetAddress.getByName("1123:4567:89ab:cdef:0123:4567:89ab:cde0"), RND.nextInt(BIT_16), - RND.nextInt(BIT_16)), null, true, true, true, true, true, false, psa); - - Assert.assertEquals(142, pa3.toByteArray().length); - - } /** * Compare two PeerAddress. @@ -234,22 +251,27 @@ public void testPeerAddress7() throws UnknownHostException { */ private void compare(final PeerAddress pa1, final PeerAddress pa2) { Assert.assertEquals(pa1.peerId(), pa2.peerId()); - Assert.assertEquals(pa1.createSocketTCP().getPort(), pa2.createSocketTCP().getPort()); - Assert.assertEquals(pa1.createSocketTCP(), pa2.createSocketTCP()); - Assert.assertEquals(pa1.createSocketUDP().getPort(), pa2.createSocketUDP().getPort()); - Assert.assertEquals(pa1.createSocketUDP(), pa2.createSocketUDP()); - Assert.assertEquals(pa1.isFirewalledTCP(), pa2.isFirewalledTCP()); - Assert.assertEquals(pa1.isFirewalledUDP(), pa2.isFirewalledUDP()); - Assert.assertEquals(pa1.isIPv6(), pa2.isIPv6()); - Assert.assertEquals(pa1.isRelayed(), pa2.isRelayed()); - Assert.assertEquals(pa1.options(), pa2.options()); + Assert.assertEquals(pa1.ipInternalNetworkPrefix(), pa2.ipInternalNetworkPrefix()); + Assert.assertEquals(pa1.holePunching(), pa2.holePunching()); + Assert.assertEquals(pa1.ipInternalSocket(), pa2.ipInternalSocket()); + Assert.assertEquals(pa1.ipv4Flag(), pa2.ipv4Flag()); + Assert.assertEquals(pa1.ipv4Socket(), pa2.ipv4Socket()); + Assert.assertEquals(pa1.ipv6Flag(), pa2.ipv6Flag()); + Assert.assertEquals(pa1.ipv6Socket(), pa2.ipv6Socket()); + Assert.assertEquals(pa1.net4Internal(), pa2.net4Internal()); + Assert.assertEquals(pa1.reachable4UDP(), pa2.reachable4UDP()); + Assert.assertEquals(pa1.reachable4TCP(), pa2.reachable4TCP()); + Assert.assertEquals(pa1.reachable4UDT(), pa2.reachable4UDT()); + Assert.assertEquals(pa1.reachable6UDP(), pa2.reachable6UDP()); + Assert.assertEquals(pa1.reachable6TCP(), pa2.reachable6TCP()); + Assert.assertEquals(pa1.reachable6UDT(), pa2.reachable6UDT()); Assert.assertEquals(pa1.relays(), pa2.relays()); - List psa1 = new ArrayList(pa1.peerSocketAddresses()); - List psa2 = new ArrayList(pa2.peerSocketAddresses()); - Assert.assertEquals(psa1.size(), psa2.size()); - for (int i = 0; i < psa1.size(); i++) { - Assert.assertEquals(psa1.get(i), psa2.get(i)); - } - + Assert.assertEquals(pa1.relaySize(), pa2.relaySize()); + Assert.assertEquals(pa1.relayTypes(), pa2.relayTypes()); + Assert.assertEquals(pa1.size(), pa2.size()); + Assert.assertEquals(pa1.slow(), pa2.slow()); + Assert.assertEquals(pa1.unreachable(), pa2.unreachable()); + Assert.assertEquals(pa1.skipIPv4(), pa2.skipIPv4()); + Assert.assertEquals(pa1.skipIPv6(), pa2.skipIPv6()); } } diff --git a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java index 40754d9e1..313e8a17e 100644 --- a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java +++ b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java @@ -40,7 +40,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; public class UtilsDHT2 { /** @@ -82,7 +82,7 @@ public static PeerAddress createAddress(String id) throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); + PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false,false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; diff --git a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java index 1193e9628..bb8675b49 100644 --- a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java +++ b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java @@ -29,7 +29,7 @@ import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.utils.Pair; @@ -582,7 +582,7 @@ private Message createSendOriginalMessage(final int localPort, final int remoteP */ private FutureDone createInitMessage(final List channelFutures) throws Exception { final FutureDone initMessageFutureDone = new FutureDone(); - final PeerSocketAddress socketAddress = Utils.extractRandomRelay(originalMessage); + final PeerSocketAddress2 socketAddress = Utils.extractRandomRelay(originalMessage); // we need to make a copy of the original Message final PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index b7c1e7b2a..8193f626e 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -25,7 +25,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMapChangeListener; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.utils.ConcurrentCacheSet; @@ -301,17 +301,17 @@ public void operationComplete(final FutureDone futureClose) */ private void updatePeerAddress() { final boolean hasRelays; - final Collection socketAddresses; + final Collection socketAddresses; synchronized (activeClients) { // add relay addresses to peer address hasRelays = !activeClients.isEmpty(); - socketAddresses = new ArrayList(activeClients.size()); + socketAddresses = new ArrayList(activeClients.size()); //we can have more than the max relay count in our active client list. int max = 5; int i = 0; for (PeerAddress relay : activeClients.keySet()) { - socketAddresses.add(new PeerSocketAddress(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); + socketAddresses.add(new PeerSocketAddress2(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); if(i++ >= max) { break; } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 6d159234c..5d82505ff 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -27,7 +27,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.NeighborRPC; @@ -88,8 +88,8 @@ public FutureDone forwardToUnreachable(final Message message) { envelope.keepAlive(true); // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress(message.sender().inetAddress(), 0, 0)); + Collection peerSocketAddresses = new ArrayList(1); + peerSocketAddresses.add(new PeerSocketAddress2(message.sender().inetAddress(), 0, 0)); envelope.peerSocketAddresses(peerSocketAddresses); // holds the message that will be returned to he requester @@ -295,8 +295,8 @@ private void forwardMessages(List buffer2) { envelope.buffer(new Buffer(bb)); // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress(envelope.sender().inetAddress(), 0, 0)); + Collection peerSocketAddresses = new ArrayList(1); + peerSocketAddresses.add(new PeerSocketAddress2(envelope.sender().inetAddress(), 0, 0)); envelope.peerSocketAddresses(peerSocketAddresses); // Forward a message through the open peer connection to the unreachable peer. diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index ae6a0bac4..2b2183e0d 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -31,7 +31,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; @@ -239,8 +239,8 @@ private Dispatcher dispatcher() { private void handleSetup(Message message, final PeerConnection unreachablePeerConnectionOrig, final Responder responder) { final Number160 unreachablePeerId = unreachablePeerConnectionOrig.remotePeer().peerId(); //add myself as relay - Collection psa = unreachablePeerConnectionOrig.remotePeer().peerSocketAddresses(); - Collection psa2 = new ArrayList(psa); + Collection psa = unreachablePeerConnectionOrig.remotePeer().peerSocketAddresses(); + Collection psa2 = new ArrayList(psa); psa2.add(peer().peerAddress().peerSocketAddress()); final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer( @@ -283,10 +283,10 @@ private void handlePiggyBackedMessage(Message message, final Responder responder // TODO: check if we have right setup // this contains the real sender - Collection peerSocketAddresses = message.peerSocketAddresses(); + Collection peerSocketAddresses = message.peerSocketAddresses(); final InetSocketAddress sender; if (!peerSocketAddresses.isEmpty()) { - sender = PeerSocketAddress.createSocketTCP(peerSocketAddresses.iterator().next()); + sender = PeerSocketAddress2.createSocketTCP(peerSocketAddresses.iterator().next()); } else { sender = new InetSocketAddress(0); } @@ -386,7 +386,7 @@ public void handleBuffer(final Message message) throws InvalidKeyException, NoSu } - private static Responder createResponder(final Peer peer, final PeerSocketAddress sender) { + private static Responder createResponder(final Peer peer, final PeerSocketAddress2 sender) { return new Responder() { @Override diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java index eb636bb5d..641295a59 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -16,7 +16,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; //travis-ci cannot test this, the kernel does not support all the required features: //Perhaps iptables or your kernel needs to be upgraded @@ -52,7 +52,7 @@ public void testForwardTwoPeers() throws Exception { try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); @@ -151,7 +151,7 @@ public void testForwardTwoPlusOne() throws Exception { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); final Peer regularPeer = LocalNATUtils.createRealNode(Number160.createHash(77), INF, 5003); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); CommandSync sync = new CommandSync(2); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java new file mode 100644 index 000000000..e30ea09ec --- /dev/null +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java @@ -0,0 +1,148 @@ +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: + * /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 Serializable discover(final String address, Peer peer) + throws UnknownHostException { + PeerAddress relayP = new PeerAddress(relayPeerId, address, 5002, 5002); + FutureDone type = NATTypeDetection.checkNATType(peer, relayP) + .awaitUninterruptibly(); + return type.isSuccess() ? type.object().name() : type.failedReason(); + } + + @SuppressWarnings("serial") + @Test + public void testDetection() throws Exception { + Peer relayPeer = null; + RemotePeer unr1 = null; + RemotePeer unr2 = null; + try { + relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); + InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); + 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 discover(address, peer); + } + }, 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"); + return discover(address, peer); + } + }, 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("."); + } + } +} diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 542ba88b5..22832896a 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -13,7 +13,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import org.junit.After; import org.junit.Assert; @@ -68,7 +68,7 @@ public void testLocalSend() throws Exception { RemotePeer unr1 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -95,7 +95,7 @@ public Serializable execute() throws Exception { // now peer1 and peer2 know each other locally. PeerAddress punr2 = peer2.peerAddress(); InetAddress internal = InetAddress.getByName("0.0.0.3"); - punr2 = punr2.changeInternalPeerSocketAddress(new PeerSocketAddress(internal, 5001, 5001)); + punr2 = punr2.changeInternalPeerSocketAddress(new PeerSocketAddress2(internal, 5001, 5001)); punr2 = punr2.changePortForwarding(true); FuturePing fp1 = peer1.ping().peerAddress(punr2).start().awaitUninterruptibly(); sb.append(fp1.isSuccess()); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index 8bdd93497..d06eb378e 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -22,7 +22,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.relay.Forwarder; import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; @@ -70,8 +70,8 @@ public void testRelayFailover1() throws Exception { try { relayPeer1 = createRelay(relayPeerId1, 5002); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); - final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); final Peer relayPeer1Copy = relayPeer1; CommandSync sync = new CommandSync(1); @@ -161,9 +161,9 @@ public void testRelayFailover2() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); final Peer relayPeer1Copy = relayPeer1; final Peer relayPeer2Copy = relayPeer2; @@ -257,15 +257,15 @@ public void testFullRelay() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); relayPeer3 = createRelay(relayPeerId3, 5004); - final PeerSocketAddress relayAddress3 = relayPeer3.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress3 = relayPeer3.peerAddress().peerSocketAddress(); relayPeer4 = createRelay(relayPeerId4, 5005); - final PeerSocketAddress relayAddress4 = relayPeer4.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress4 = relayPeer4.peerAddress().peerSocketAddress(); relayPeer5 = createRelay(relayPeerId5, 5006); - final PeerSocketAddress relayAddress5 = relayPeer5.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress5 = relayPeer5.peerAddress().peerSocketAddress(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -330,9 +330,9 @@ public void testLateRelay() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -458,7 +458,7 @@ public void testRealRelayDifferentNAT() throws Exception { RemotePeer unr2 = null; try { relayPeer = createRelay(relayPeerId1, 5002); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); CommandSync sync = new CommandSync(2); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -478,7 +478,7 @@ public Serializable execute() throws Exception { Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.1.2", 5000, 1); - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(relayAddress); peer2 = peer2.changePeerSocketAddresses(psa); peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); @@ -519,7 +519,7 @@ public Serializable execute() throws Exception { Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.0.2", 5000, 0); - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(relayAddress); peer2 = peer2.changePeerSocketAddresses(psa); peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); @@ -611,7 +611,7 @@ public void testRealRelaySameNAT() throws Exception { RemotePeer unr1 = null; try { relayPeer = createRelay(relayPeerId1, 5002); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index 9c7b201a4..45680911f 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -26,7 +26,7 @@ import net.tomp2p.p2p.RequestP2PConfiguration; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.relay.RelayCallback; import net.tomp2p.storage.Data; @@ -94,8 +94,8 @@ public void testStress() throws Exception { relayDHT1 = new PeerBuilderDHT(relayPeer1).start(); final Peer relayPeer11 = relayPeer1; relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); - final PeerSocketAddress relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); System.out.println("relay 1:"+relayPeer1.peerAddress()); System.out.println("relay 2:"+relayPeer2.peerAddress()); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java index 4fdd16540..7feaceb50 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java @@ -21,7 +21,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.storage.Data; //travis-ci cannot test this, the kernel does not support all the required features: @@ -58,7 +58,7 @@ public void testUPNP() throws Exception { try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); pd = new PeerBuilderDHT(relayPeer).start(); - final PeerSocketAddress relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java b/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java index a038e52b9..7624c65b4 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java @@ -18,7 +18,7 @@ import net.tomp2p.message.Buffer; import net.tomp2p.message.Message; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import org.junit.Assert; import org.junit.Test; @@ -51,10 +51,10 @@ public void testEncodeDecodeRelayedMessage() throws InvalidKeyException, Signatu InvalidKeySpecException { Message message = UtilsNAT.createRandomMessage(); - List relays = new ArrayList(); - relays.add(new PeerSocketAddress(InetAddress.getLocalHost(), 8000, 9000)); - relays.add(new PeerSocketAddress(InetAddress.getLocalHost(), 8001, 9001)); - relays.add(new PeerSocketAddress(InetAddress.getLocalHost(), 8002, 9002)); + List relays = new ArrayList(); + relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8000, 9000)); + relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8001, 9001)); + relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8002, 9002)); PeerAddress sender = UtilsNAT.createRandomAddress().changeRelayed(true).changePeerSocketAddresses(relays) .changeFirewalledTCP(true).changeFirewalledUDP(true); diff --git a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java index 178450835..0b99ed002 100644 --- a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java +++ b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java @@ -33,7 +33,7 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.rpc.RPC.Commands; public class UtilsNAT { @@ -212,7 +212,7 @@ public static PeerAddress createRandomAddress() throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); + PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; diff --git a/pom.xml b/pom.xml index 4df52f82a..a38dad26a 100644 --- a/pom.xml +++ b/pom.xml @@ -92,10 +92,16 @@ - org.slf4j - slf4j-api - 1.7.5 - + org.slf4j + slf4j-api + 1.7.5 + + + org.projectlombok + lombok + 1.16.6 + provided + @@ -203,6 +209,19 @@ -Dio.netty.leakDetectionLevel=advanced + + org.projectlombok + lombok-maven-plugin + 1.16.6.1 + + + generate-sources + + delombok + + + + diff --git a/replication/src/test/java/net/tomp2p/Utils2.java b/replication/src/test/java/net/tomp2p/Utils2.java index 13ab3d3ca..3e7d04238 100644 --- a/replication/src/test/java/net/tomp2p/Utils2.java +++ b/replication/src/test/java/net/tomp2p/Utils2.java @@ -41,7 +41,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.replication.IndirectReplication; public class Utils2 { @@ -84,7 +84,7 @@ public static PeerAddress createAddress(String id) throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress peerSocketAddress = new PeerSocketAddress(inetSend, tcpPortSender, udpPortSender); + PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); return n1; From f367156643f4aa9ac174971272c358fce9aa99e7 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 2 Nov 2015 19:01:30 +0100 Subject: [PATCH 111/135] further fixes and improvements for NAT and IPv6 --- .../java/net/tomp2p/connection/Ports.java | 2 +- .../main/java/net/tomp2p/message/Decoder.java | 6 +- .../main/java/net/tomp2p/message/Message.java | 18 ++- .../tomp2p/message/MessageHeaderCodec.java | 4 +- .../main/java/net/tomp2p/p2p/PeerBuilder.java | 6 +- .../main/java/net/tomp2p/peers/Number160.java | 2 +- .../java/net/tomp2p/peers/PeerAddress.java | 87 +++++++++---- .../src/main/java/net/tomp2p/utils/Utils.java | 8 +- core/src/test/java/net/tomp2p/Utils2.java | 23 ++++ .../java/net/tomp2p/message/TestMessage.java | 122 +++++++++++------- .../net/tomp2p/peers/TestPeerAddress.java | 2 +- .../java/net/tomp2p/peers/TestPeerMap.java | 84 ++++++------ .../java/net/tomp2p/rpc/TestBloomFilter.java | 10 +- .../java/net/tomp2p/rpc/TestNeighbor.java | 8 +- 14 files changed, 242 insertions(+), 140 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/Ports.java b/core/src/main/java/net/tomp2p/connection/Ports.java index b795d485e..adcc2149f 100644 --- a/core/src/main/java/net/tomp2p/connection/Ports.java +++ b/core/src/main/java/net/tomp2p/connection/Ports.java @@ -58,7 +58,7 @@ public Ports() { */ public Ports(final int tcpPort, final int udpPort, final int udtPort) { if(tcpPort < 1 || udpPort < 1 || udtPort < 1) { - throw new IllegalArgumentException("manual ports need to be > 1"); + throw new IllegalArgumentException("manual ports need to be > 1. TCP: "+tcpPort+", UDP:"+udpPort+", UDT:"+udtPort); } this.tcpPort = tcpPort; this.udpPort = udpPort; diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index 40eb1bbda..a2d3bad9b 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -169,15 +169,15 @@ private void verifySignature(final ByteBuf buf, final int readerBefore, final in } public boolean decodeHeader(final ByteBuf buf, InetSocketAddress recipient, final InetSocketAddress sender) { - if (message == null) { + if (!headerDone) { if (buf.readableBytes() < MessageHeaderCodec.HEADER_SIZE_MIN) { // we don't have the header yet, we need the full header first // wait for more data return false; } final int readerIndex = buf.readerIndex(); - final boolean success = MessageHeaderCodec.decodeHeader(buf, recipient, sender, message); - if(!success) { + headerDone = MessageHeaderCodec.decodeHeader(buf, recipient, sender, message); + if(!headerDone) { buf.readerIndex(readerIndex); return false; } diff --git a/core/src/main/java/net/tomp2p/message/Message.java b/core/src/main/java/net/tomp2p/message/Message.java index 7f3a441dc..aeea047ad 100644 --- a/core/src/main/java/net/tomp2p/message/Message.java +++ b/core/src/main/java/net/tomp2p/message/Message.java @@ -34,6 +34,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.Number640; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.rpc.RPC; @@ -880,6 +881,21 @@ public PublicKey publicKey(final int index) { return publicKeyList.get(index); } + public Message peerSocketAddress(final PeerSocketAddress peerSocketAddress) { + if(peerSocketAddress instanceof PeerSocket4Address) { + return peerSocket4Address((PeerSocket4Address)peerSocketAddress); + } else { + return peerSocket6Address((PeerSocket6Address)peerSocketAddress); + } + } + + public List peerSocketAddressList() { + List retVal = new ArrayList(); + retVal.addAll(peerSocket4AddressList()); + retVal.addAll(peerSocket6AddressList()); + return retVal; + } + public Message peerSocket4Address(final PeerSocket4Address peerSocket4Address) { if (!presetContentTypes) { contentType(Content.PEER_SOCKET4); @@ -1000,7 +1016,7 @@ public SignatureCodec receivedSignature() { @Override public String toString() { final StringBuilder sb = new StringBuilder("msgid="); - return sb.append(messageId()).append(",t=").append(type.toString()). + return sb.append(messageId()).append(",t=").append(type). append(",c=").append(RPC.Commands.find(command).toString()).append(",").append(isUdp()?"udp":"tcp"). append(",s=").append(sender).append(",r=").append(recipient).toString(); } diff --git a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java index f3aac237e..e15c7b517 100644 --- a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java +++ b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java @@ -80,7 +80,7 @@ public static void encodeHeader(final ByteBuf buf, final Message message, final buf.writeInt(versionAndType); // 4 buf.writeInt(message.messageId()); // 8 buf.writeByte(message.command()); // 9 - buf.writeBytes(message.recipient().peerId().toByteArray()); // 29 + message.recipient().peerId().encode(buf); //29 buf.writeInt(encodeContentTypes(message.contentTypes())); // 33 // three bits for the message options, 5 bits for the sender options buf.writeByte(message.options()); // 34 @@ -127,7 +127,7 @@ public static boolean decodeHeader(final ByteBuf buffer, final InetSocketAddress if(buffer.readableBytes() < peerAddressSize) { return false; } - PeerAddress peerAddress = PeerAddress.decode(buffer); + PeerAddress peerAddress = PeerAddress.decode(header, buffer); if(senderSocket.getAddress() instanceof Inet4Address) { PeerSocket4Address psa4 = peerAddress.ipv4Socket().withIpv4(IPv4.fromInet4Address(senderSocket.getAddress())); message.sender(peerAddress.withIpv4Socket(psa4)); diff --git a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java index 4ac03ae7e..d48bc6344 100644 --- a/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/PeerBuilder.java @@ -194,7 +194,11 @@ public Peer start() throws IOException { channelServerConfiguration.ports(new Ports(tcpPort, udpPort, udpPort + 1)); } - channelServerConfiguration.portsForwarding(new Ports(tcpPortForwarding, udpPortForwarding, udpPortForwarding + 1)); + if(tcpPortForwarding == -1 && udpPortForwarding == -1) { + channelServerConfiguration.portsForwarding(new Ports()); + } else { + channelServerConfiguration.portsForwarding(new Ports(tcpPortForwarding, udpPortForwarding, udpPortForwarding + 1)); + } if (channelClientConfiguration == null) { channelClientConfiguration = createDefaultChannelClientConfiguration(); diff --git a/core/src/main/java/net/tomp2p/peers/Number160.java b/core/src/main/java/net/tomp2p/peers/Number160.java index 3f2cb8863..3bb25933a 100644 --- a/core/src/main/java/net/tomp2p/peers/Number160.java +++ b/core/src/main/java/net/tomp2p/peers/Number160.java @@ -490,7 +490,7 @@ public int encode(byte[] me, int offset) { } public Number160 encode(ByteBuf buf) { - buf.writeInt(val[0]).writeInt(val[1]).writeInt(val[2]).writeInt(val[3]).writeInt(val[4]).writeInt(val[5]); + buf.writeInt(val[0]).writeInt(val[1]).writeInt(val[2]).writeInt(val[3]).writeInt(val[4]); return this; } } diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 9184632cf..23995e42f 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -213,6 +213,54 @@ public PeerAddressBuilder ipInternalSocket(PeerSocket4Address ipInternalSocket) } + public PeerAddress withRelays(Collection relays) { + if(this.relays == relays) { + return this; + } + + final int relaySize; + final BitSet relayTypes = new BitSet(8); + if(relays != null) { + relaySize = relays.size(); + int index=0; + for(PeerSocketAddress relay: relays) { + if(relay instanceof PeerSocket4Address) { + relayTypes.set(index++, false); + } + else { + relayTypes.set(index++, true); + } + } + } else { + relaySize = 0; + } + + + return this.relays == relays ? this : new PeerAddress(ipInternalSocket, + ipInternalNetworkPrefix, + ipv4Socket, + ipv6Socket, + ipv4Flag, + ipv6Flag, + reachable4UDP, + reachable4TCP, + reachable4UDT, + reachable6UDP, + reachable6TCP, + reachable6UDT, + peerId, + relaySize, + slow, + holePunching, + unreachable, + net4Internal, + skipIPv4, + skipIPv6, + relayTypes, + hashCode, + relays); + } + public Collection relays() { @@ -241,22 +289,15 @@ public static Pair decode(final byte[] array) { return decode(array, 0); } - /** - * Creates a PeerAddress from a continuous byte array. This is useful if you don't know the size beforehand. The new - * offset can be accessed with offset(). - * - * @param me - * The serialized array - * @param initialOffset - * the offset, where to start - */ public static Pair decode(final byte[] array, int offset) { + final int header = Utils.byteArrayToMedium(array, offset); + offset+=3; + return decode(header, array, offset); + } + public static Pair decode(final int header, final byte[] array, int offset) { final PeerAddressBuilder builder = new PeerAddressBuilder(); - final int header = Utils.byteArrayToMedium(array, offset); - offset+=3; - - decodeHeader(builder, header); + decodeHeader(builder, header); //relays for(int i = 0; i decode(final byte[] array, int offset) return new Pair(peerAddress, pair.element1()); } - /** - * Creates a PeerAddress from a Netty ByteBuf. - * - * @param channelBuffer - * The channel buffer to read from - */ public static PeerAddress decode(final ByteBuf buf) { + final int header = buf.readUnsignedMedium(); + return decode(header, buf); + } + public static PeerAddress decode(final int header, final ByteBuf buf) { final PeerAddressBuilder builder = new PeerAddressBuilder(); - final int header = buf.readUnsignedMedium(); decodeHeader(builder, header); //relays for(int i=0;i psa, PeerSocket4Address ipv4Socket) { + if(address instanceof Inet4Address) { + return PeerAddress.builder() + .peerId(id) + .ipv4Socket((PeerSocket4Address)creatPeerSocket(address, portTCP, portUDP)) + .relay(psa) + .ipInternalSocket(ipv4Socket) + .build(); + } else { + return PeerAddress.builder() + .peerId(id) + .ipv6Socket((PeerSocket6Address)creatPeerSocket(address, portTCP, portUDP)) + .ipv4Socket(ipv4Socket) + .relay(psa) + .build(); + } + } public static PeerAddress createPeerAddress(Number160 id, Inet6Address address, int portTCP, int portUDP, Collection psa, PeerSocket4Address creatPeerSocket, PeerSocket4Address creatPeerSocket2) { @@ -411,6 +430,10 @@ public static PeerAddress createPeerAddress(Number160 id, Inet6Address address, } + public static PeerAddress createPeerAddress(Number160 id1) { + return PeerAddress.builder().peerId(id1).build(); + } + diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index bca67e1e9..b3ba01905 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -19,14 +19,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import io.netty.channel.socket.DatagramChannel; -import io.netty.util.Attribute; -import io.netty.util.AttributeKey; import java.io.IOException; import java.net.InetAddress; @@ -48,17 +40,6 @@ import java.util.TreeMap; import java.util.concurrent.atomic.AtomicReference; -import net.tomp2p.Utils2; -import net.tomp2p.connection.DSASignatureFactory; -import net.tomp2p.message.Message.Content; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.Number640; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; -import net.tomp2p.storage.AlternativeCompositeByteBuf; -import net.tomp2p.storage.Data; -import net.tomp2p.utils.Utils; - import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -70,6 +51,27 @@ import com.cedarsoftware.util.DeepEquals; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.socket.DatagramChannel; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; +import net.tomp2p.Utils2; +import net.tomp2p.connection.DSASignatureFactory; +import net.tomp2p.message.Message.Content; +import net.tomp2p.peers.Number160; +import net.tomp2p.peers.Number640; +import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.TestPeerAddress; +import net.tomp2p.storage.AlternativeCompositeByteBuf; +import net.tomp2p.storage.Data; +import net.tomp2p.utils.Utils; + /** * Tests encoding of an empty message. These tests should not be used for * performance measuremenst, since mockito is used, and I guess this would @@ -149,6 +151,7 @@ public void testEncodeDecode() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, m2); } @@ -175,6 +178,7 @@ public void testEncodeDecode2() throws Exception { // encode m1.keyCollection(new KeyCollection(tmp2)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(false, m2.keyList() == null); Assert.assertEquals(false, m2.keyCollectionList() == null); @@ -195,6 +199,7 @@ public void testEncodeDecode3() throws Exception { // encode ByteBuf tmp = Unpooled.wrappedBuffer(me); m1.buffer(new Buffer(tmp)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(false, m2.buffer(0) == null); compareMessage(m1, m2); } @@ -236,6 +241,7 @@ public void testEncodeDecode4() throws Exception { m1.keyMap640Keys(new KeyMap640Keys(keysMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(true, m2.publicKey(0) != null); Assert.assertEquals(false, m2.dataMap(0) == null); Assert.assertEquals(false, m2.keyMap640Keys(0) == null); @@ -276,6 +282,7 @@ public void testEncodeDecode5() throws Exception { m1.keyMap640Keys(new KeyMap640Keys(keysMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(true, m2.publicKey(0) != null); Assert.assertEquals(false, m2.dataMap(0) == null); Assert.assertEquals(false, m2.keyMap640Keys(0) == null); @@ -315,6 +322,7 @@ public void testEncodeDecode7() throws Exception { m1.keyMap640Keys(new KeyMap640Keys(keysMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(true, m2.publicKey(0) != null); Assert.assertEquals(false, m2.dataMap(0) == null); Assert.assertEquals(false, m2.dataMap(0).dataMap().entrySet().iterator().next().getValue().signature() == null); @@ -331,6 +339,7 @@ public void testEncodeDecode6() throws Exception { // ipv4 Message m1 = Utils2.createDummyMessage((i & 1) > 0, (i & 2) > 0); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, m2); } } @@ -363,6 +372,7 @@ public void testBigData() throws Exception { dataMap.put(new Number640(rnd), data); m1.setDataMap(new DataMap(dataMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, m2); } @@ -381,6 +391,7 @@ public void testBigDataSigned() throws Exception { dataMap.put(new Number640(rnd), data); m1.setDataMap(new DataMap(dataMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, m2); } @@ -404,6 +415,7 @@ public void testEncodeDecode480MapRep() throws Exception { // encode Message m2 = encodeDecode(m1); Assert.assertEquals(true, m2.publicKey(0) != null); m2.release(); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, m2); } @@ -425,6 +437,7 @@ public void testEncodeDecode480MapReq() throws Exception { // encode } m1.setDataMap(new DataMap(dataMap)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(true, m2.publicKey(0) != null); compareMessage(m1, m2); } @@ -444,6 +457,7 @@ public void testEncodeDecode480Set() throws Exception { // encode } m1.keyCollection(new KeyCollection(list)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(true, m2.publicKey(0) != null); compareMessage(m1, m2); } @@ -463,6 +477,7 @@ public void serializationTest() throws IOException, ClassNotFoundException, boolean payload = d.decodePayload(buf); Assert.assertEquals(true, header); Assert.assertEquals(true, payload); + m1.sender(m1.sender().withSkipIPv4(true)); compareMessage(m1, d.message()); buf.release(); @@ -485,19 +500,23 @@ public void serializationTestFail() throws IOException, public void testRelayAddresses1() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); m1.type(Message.Type.NOT_FOUND); - List tmp = new ArrayList(); + List tmp = new ArrayList(); tmp.add(Utils2.creatPeerSocket(InetAddress.getLocalHost(), 15, 17)); tmp.add(Utils2.creatPeerSocket(InetAddress.getByName("0:0:0:0:0:0:0:1"), 16, 18)); - m1.peerSocketAddresses(tmp); + + m1.peerSocketAddress(Utils2.creatPeerSocket(InetAddress.getLocalHost(), 15, 17)); + m1.peerSocketAddress(Utils2.creatPeerSocket(InetAddress.getByName("0:0:0:0:0:0:0:1"), 16, 18)); + m1.sender(m1.sender().withRelays(tmp)); Message m2 = encodeDecode(m1); - Assert.assertEquals(tmp, m2.peerSocketAddresses()); + m1.sender(m1.sender().withSkipIPv4(true)); + Assert.assertEquals(tmp, m2.peerSocketAddressList()); compareMessage(m1, m2); } @Test public void testRelay() throws Exception { - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), @@ -508,8 +527,12 @@ public void testRelay() throws Exception { RND.nextInt(BIT_16), RND.nextInt(BIT_16))); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerSocketAddress2 psaa = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa, psa); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.233"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.234"), RND.nextInt(BIT_16), + RND.nextInt(BIT_16))); + + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), InetAddress.getByName("192.168.230.236"),RND.nextInt(BIT_16), RND.nextInt(BIT_16), psa); @@ -519,6 +542,7 @@ public void testRelay() throws Exception { m1.neighborsSet(new NeighborSet(-1, tmp)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertArrayEquals(psa.toArray(), m2.neighborsSet(0).neighbors().iterator().next().relays().toArray()); compareMessage(m1, m2); @@ -526,7 +550,7 @@ public void testRelay() throws Exception { @Test public void testRelay2() throws Exception { - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), @@ -537,15 +561,21 @@ public void testRelay2() throws Exception { RND.nextInt(BIT_16), RND.nextInt(BIT_16))); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerSocketAddress2 psaa = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa, psa); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("5123:4567:89ab:cdef:0123:4567:89ab:cde4"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + psa.add(Utils2.creatPeerSocket(InetAddress.getByName("6123:4567:89ab:cdef:0123:4567:89ab:cde4"), + RND.nextInt(BIT_16), RND.nextInt(BIT_16))); + + + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), InetAddress.getByName("192.168.230.232"),RND.nextInt(BIT_16), RND.nextInt(BIT_16), psa); Message m1 = Utils2.createDummyMessage(); Collection tmp = new ArrayList(); tmp.add(pa3); - m1.neighborsSet(new NeighborSet(100, tmp)); + m1.neighborsSet(new NeighborSet(152, tmp)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(tmp, m2.neighborsSetList().get(0).neighbors()); compareMessage(m1, m2); @@ -553,7 +583,7 @@ public void testRelay2() throws Exception { @Test public void testInternalPeerSocket() throws Exception { - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.230"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); psa.add(Utils2.creatPeerSocket(InetAddress.getByName("2123:4567:89ab:cdef:0123:4567:89ab:cde2"), @@ -565,9 +595,13 @@ public void testInternalPeerSocket() throws Exception { psa.add(Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.232"), RND.nextInt(BIT_16), RND.nextInt(BIT_16))); - PeerSocketAddress2 psaa1 = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerSocketAddress2 psaa2 = Utils2.creatPeerSocket(InetAddress.getByName("0.0.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); - PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"),psaa1, psaa2, psa); + //PeerSocketAddress psaa1 = Utils2.creatPeerSocket(InetAddress.getByName("192.168.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + PeerSocketAddress psaa2 = Utils2.creatPeerSocket(InetAddress.getByName("0.0.230.236"), RND.nextInt(BIT_16), RND.nextInt(BIT_16)); + + PeerAddress pa3 = Utils2.createPeerAddress(new Number160("0x657435a424444522456"), InetAddress.getByName("192.168.230.232"),RND.nextInt(BIT_16), RND.nextInt(BIT_16), psa, (PeerSocket4Address)psaa2); + + + Message m1 = Utils2.createDummyMessage(); @@ -576,6 +610,8 @@ public void testInternalPeerSocket() throws Exception { m1.neighborsSet(new NeighborSet(100, tmp)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(tmp, m2.neighborsSetList().get(0).neighbors()); compareMessage(m1, m2); @@ -588,6 +624,7 @@ public void testSlowFlag() throws Exception { // encode m1.sender(m1.sender().withSlow(true)); Message m2 = encodeDecode(m1); + m1.sender(m1.sender().withSkipIPv4(true)); Assert.assertEquals(m1.sender().slow(), m2.sender().slow()); compareMessage(m1, m2); } @@ -631,8 +668,8 @@ private Message encodeDecode(final Message m1) throws Exception { encoder.write(buf, m1, null, false); ChannelHandlerContext ctx = mockChannelHandlerContext(buf, m2); Decoder decoder = new Decoder(new DSASignatureFactory()); - decoder.decode(ctx, buf, m1.recipient().createSocket4TCP(), m1 - .sender().createSocket4TCP()); + decoder.decode(ctx, buf, m1.recipient().ipv4Socket().createTCPSocket(), m1 + .sender().ipv4Socket().createTCPSocket()); buf.release(); return decoder.message(); } @@ -740,20 +777,7 @@ private void comparePeerAddresses(final PeerAddress p1, final PeerAddress p2, bo Assert.assertEquals(p1.peerId(), p2.peerId()); if(isSender) { - Assert.assertEquals(p1.peerSocketAddress(), p2.peerSocketAddress()); - Assert.assertEquals(p1.unreachable(), p2.unreachable()); - Assert.assertEquals(p1.relays(), p2.relays()); - Assert.assertEquals(p1.relaySize(), p2.relaySize()); - Assert.assertEquals(p1.slow(), p2.slow()); - Assert.assertEquals(p1.holePunching(), p2.holePunching()); - - //tests are currently only IPv4 - Assert.assertEquals(p1.peerSocketAddress().ipv6Flag(), p2.peerSocketAddress().ipv6Flag()); - - Assert.assertEquals(p1.peerSocketAddress().net4Internal(), p1.peerSocketAddress().net4Internal()); - Assert.assertEquals(p1.peerSocketAddress().reachableTCP(), p1.peerSocketAddress().reachableTCP()); - Assert.assertEquals(p1.peerSocketAddress().reachableUDP(), p1.peerSocketAddress().reachableUDP()); - Assert.assertEquals(p1.peerSocketAddress().reachableUDT(), p1.peerSocketAddress().reachableUDT()); + TestPeerAddress.compare(p1, p2); } } diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java index 81b935909..41a66465f 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerAddress.java @@ -249,7 +249,7 @@ public void testPeerAddress6() throws UnknownHostException { * @param pa2 * The second PeerAddress */ - private void compare(final PeerAddress pa1, final PeerAddress pa2) { + public static void compare(final PeerAddress pa1, final PeerAddress pa2) { Assert.assertEquals(pa1.peerId(), pa2.peerId()); Assert.assertEquals(pa1.ipInternalNetworkPrefix(), pa2.ipInternalNetworkPrefix()); Assert.assertEquals(pa1.holePunching(), pa2.holePunching()); diff --git a/core/src/test/java/net/tomp2p/peers/TestPeerMap.java b/core/src/test/java/net/tomp2p/peers/TestPeerMap.java index 6b4843ce8..38f176482 100644 --- a/core/src/test/java/net/tomp2p/peers/TestPeerMap.java +++ b/core/src/test/java/net/tomp2p/peers/TestPeerMap.java @@ -95,12 +95,12 @@ public void testAdd1() { Assert.assertEquals(1, PeerMap.classMember(Number160.ZERO, id1)); Assert.assertEquals(159, PeerMap.classMember(Number160.ZERO, Number160.MAX_VALUE)); // - PeerAddress pa1 = new PeerAddress(id1); - PeerAddress pa2 = new PeerAddress(id2); - PeerAddress pa3 = new PeerAddress(id3); - PeerAddress pa4 = new PeerAddress(id4); - PeerAddress pa5 = new PeerAddress(id5); - PeerAddress pa6 = new PeerAddress(id6); + PeerAddress pa1 = Utils2.createPeerAddress(id1); + PeerAddress pa2 = Utils2.createPeerAddress(id2); + PeerAddress pa3 = Utils2.createPeerAddress(id3); + PeerAddress pa4 = Utils2.createPeerAddress(id4); + PeerAddress pa5 = Utils2.createPeerAddress(id5); + PeerAddress pa6 = Utils2.createPeerAddress(id6); peerMap.peerFound(pa1, null, null, null); peerMap.peerFound(pa2, null, null, null); peerMap.peerFound(pa3, null, null, null); @@ -136,12 +136,12 @@ public void testAdd2() { Number160 id5 = new Number160("0x6"); Number160 id6 = new Number160("0x7"); // - PeerAddress pa1 = new PeerAddress(id1); - PeerAddress pa2 = new PeerAddress(id2); - PeerAddress pa3 = new PeerAddress(id3); - PeerAddress pa4 = new PeerAddress(id4); - PeerAddress pa5 = new PeerAddress(id5); - PeerAddress pa6 = new PeerAddress(id6); + PeerAddress pa1 = Utils2.createPeerAddress(id1); + PeerAddress pa2 = Utils2.createPeerAddress(id2); + PeerAddress pa3 = Utils2.createPeerAddress(id3); + PeerAddress pa4 = Utils2.createPeerAddress(id4); + PeerAddress pa5 = Utils2.createPeerAddress(id5); + PeerAddress pa6 = Utils2.createPeerAddress(id6); peerMap.peerFound(pa1, null, null, null); peerMap.peerFound(pa2, null, null, null); peerMap.peerFound(pa3, null, null, null); @@ -182,13 +182,13 @@ public void testLength() { @Test public void testCloser() throws UnknownHostException { - PeerAddress rn1 = new PeerAddress(new Number160("0x7f")); - PeerAddress rn2 = new PeerAddress(new Number160("0x40")); + PeerAddress rn1 = Utils2.createPeerAddress(new Number160("0x7f")); + PeerAddress rn2 = Utils2.createPeerAddress(new Number160("0x40")); Number160 key = new Number160("0xff"); Assert.assertEquals(-1, PeerMap.isKadCloser(key, rn1, rn2)); // - rn1 = new PeerAddress(new Number160("0x10")); - rn2 = new PeerAddress(new Number160("0x11")); + rn1 = Utils2.createPeerAddress(new Number160("0x10")); + rn2 = Utils2.createPeerAddress(new Number160("0x11")); key = new Number160("0xff"); System.err.println("0x7f xor 0xff " + rn1.peerId().xor(key)); System.err.println("0x40 xor 0xff " + rn2.peerId().xor(key)); @@ -197,9 +197,9 @@ public void testCloser() throws UnknownHostException { @Test public void testCloser2() throws UnknownHostException { - PeerAddress rn1 = new PeerAddress(new Number160(98)); - PeerAddress rn2 = new PeerAddress(new Number160(66)); - PeerAddress rn3 = new PeerAddress(new Number160(67)); + PeerAddress rn1 = Utils2.createPeerAddress(new Number160(98)); + PeerAddress rn2 = Utils2.createPeerAddress(new Number160(66)); + PeerAddress rn3 = Utils2.createPeerAddress(new Number160(67)); PeerMapConfiguration conf = new PeerMapConfiguration(ID); conf.setFixedVerifiedBagSizes(3).setFixedOverflowBagSizes(3); conf.offlineCount(1000).offlineTimeout(60); @@ -220,7 +220,7 @@ public void testAddNode() throws UnknownHostException { conf.addMapPeerFilter(new DefaultPeerFilter()).maintenance(new DefaultMaintenance(0, new int[] {})); PeerMap peerMap = new PeerMap(conf); for (int i = 1; i < 12; i++) { - PeerAddress r1 = new PeerAddress(new Number160(i)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160(i)); peerMap.peerFound(r1, null, null, null); } SortedSet close = peerMap.closePeers(new Number160(2), 2); @@ -237,7 +237,7 @@ public void testAddNode2() throws UnknownHostException { conf.addMapPeerFilter(new DefaultPeerFilter()).maintenance(new DefaultMaintenance(0, new int[] {})); PeerMap peerMap = new PeerMap(conf); for (int i = 1; i < 12; i++) { - PeerAddress r1 = new PeerAddress(new Number160((i % 6) + 1)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160((i % 6) + 1)); peerMap.peerFound(r1, null, null, null); } SortedSet close = peerMap.closePeers(new Number160(2), 2); @@ -254,19 +254,19 @@ public void testRemove() throws UnknownHostException, InterruptedException { conf.addMapPeerFilter(new DefaultPeerFilter()).maintenance(new DefaultMaintenance(0, new int[] {})); PeerMap peerMap = new PeerMap(conf); for (int i = 1; i <= 200; i++) { - PeerAddress r1 = new PeerAddress(new Number160(i + 1)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160(i + 1)); peerMap.peerFound(r1, null, null, null); } Assert.assertEquals(20, peerMap.size()); - peerMap.peerFailed(new PeerAddress(new Number160(100)), new PeerException(AbortCause.PROBABLY_OFFLINE, "probably offline")); - Assert.assertTrue(peerMap.isPeerRemovedTemporarly(new PeerAddress(new Number160(100)))); + peerMap.peerFailed(Utils2.createPeerAddress(new Number160(100)), new PeerException(AbortCause.PROBABLY_OFFLINE, "probably offline")); + Assert.assertTrue(peerMap.isPeerRemovedTemporarly(Utils2.createPeerAddress(new Number160(100)))); Assert.assertEquals(20, peerMap.size()); - peerMap.peerFailed(new PeerAddress(new Number160(2)), new PeerException(AbortCause.PROBABLY_OFFLINE, "probably offline")); + peerMap.peerFailed(Utils2.createPeerAddress(new Number160(2)), new PeerException(AbortCause.PROBABLY_OFFLINE, "probably offline")); Assert.assertEquals(19, peerMap.size()); - Assert.assertTrue(peerMap.isPeerRemovedTemporarly(new PeerAddress(new Number160(2)))); + Assert.assertTrue(peerMap.isPeerRemovedTemporarly(Utils2.createPeerAddress(new Number160(2)))); Thread.sleep(1000); - Assert.assertFalse(peerMap.isPeerRemovedTemporarly(new PeerAddress(new Number160(2)))); - Assert.assertFalse(peerMap.isPeerRemovedTemporarly(new PeerAddress(new Number160(100)))); + Assert.assertFalse(peerMap.isPeerRemovedTemporarly(Utils2.createPeerAddress(new Number160(2)))); + Assert.assertFalse(peerMap.isPeerRemovedTemporarly(Utils2.createPeerAddress(new Number160(100)))); } @@ -278,7 +278,7 @@ public void testRemoveConcurrent() throws UnknownHostException, InterruptedExcep conf.addMapPeerFilter(new DefaultPeerFilter()).maintenance(new DefaultMaintenance(0, new int[] {})); final PeerMap peerMap = new PeerMap(conf); for (int i = 1; i <= 200; i++) { - PeerAddress r1 = new PeerAddress(new Number160(i + 1)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160(i + 1)); peerMap.peerFound(r1, null, null, null); } Assert.assertEquals(20, peerMap.size()); @@ -286,7 +286,7 @@ public void testRemoveConcurrent() throws UnknownHostException, InterruptedExcep @Override public void run() { for (int i = 1; i <= 50; i++) { - peerMap.peerFailed(new PeerAddress(new Number160(i + 1)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); + peerMap.peerFailed(Utils2.createPeerAddress(new Number160(i + 1)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); } } }); @@ -295,7 +295,7 @@ public void run() { @Override public void run() { for (int i = 1; i <= 100; i++) { - peerMap.peerFailed(new PeerAddress(new Number160(i + 1)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); + peerMap.peerFailed(Utils2.createPeerAddress(new Number160(i + 1)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); } } }); @@ -304,7 +304,7 @@ public void run() { t1.join(); t2.join(); - Assert.assertTrue(peerMap.isPeerRemovedTemporarly(new PeerAddress(new Number160(100)))); + Assert.assertTrue(peerMap.isPeerRemovedTemporarly(Utils2.createPeerAddress(new Number160(100)))); Assert.assertEquals(3, peerMap.size()); } @@ -319,7 +319,7 @@ public void testAddConcurrent() throws UnknownHostException, InterruptedExceptio @Override public void run() { for (int i = 1; i <= 50; i++) { - peerMap.peerFound(new PeerAddress(new Number160(i + 1)), null, null, null); + peerMap.peerFound(Utils2.createPeerAddress(new Number160(i + 1)), null, null, null); } } }); @@ -328,7 +328,7 @@ public void run() { @Override public void run() { for (int i = 1; i <= 100; i++) { - peerMap.peerFound(new PeerAddress(new Number160(i + 1)), null, null, null); + peerMap.peerFound(Utils2.createPeerAddress(new Number160(i + 1)), null, null, null); } } }); @@ -378,13 +378,13 @@ public void testRandomAddRemove() throws InterruptedException { public void run() { for (int i = 1; i <= rounds + diff; i++) { if (i + diff < rounds) { - boolean retVal = peerMap.peerFound(new PeerAddress(new Number160(i + 1)), null, null, null); + boolean retVal = peerMap.peerFound(Utils2.createPeerAddress(new Number160(i + 1)), null, null, null); if (retVal) { add.incrementAndGet(); } } if (i - diff > 1) { - boolean retVal = peerMap.peerFailed(new PeerAddress(new Number160(i - diff)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); + boolean retVal = peerMap.peerFailed(Utils2.createPeerAddress(new Number160(i - diff)), new PeerException(AbortCause.SHUTDOWN, "shutdown")); if (retVal) { del.incrementAndGet(); } @@ -418,7 +418,7 @@ public void testPerformance() throws IOException { long start = System.currentTimeMillis(); int size = 500000; for (int i = 1; i <= size; i++) { - PeerAddress r1 = new PeerAddress(new Number160(random)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160(random)); listAdded.add(r1); } for (PeerAddress r1 : listAdded) { @@ -461,10 +461,10 @@ public void testOrder() { Number160 b2 = new Number160("0x32"); Number160 b3 = new Number160("0x1F4"); Number160 b4 = new Number160("0x1388"); - PeerAddress n1 = new PeerAddress(b1); - PeerAddress n2 = new PeerAddress(b2); - PeerAddress n3 = new PeerAddress(b3); - PeerAddress n4 = new PeerAddress(b4); + PeerAddress n1 = Utils2.createPeerAddress(b1); + PeerAddress n2 = Utils2.createPeerAddress(b2); + PeerAddress n3 = Utils2.createPeerAddress(b3); + PeerAddress n4 = Utils2.createPeerAddress(b4); final NavigableSet queue = new TreeSet(PeerMap.createXORAddressComparator(b3)); queue.add(n1); queue.add(n2); @@ -525,7 +525,7 @@ private void testClose(int round) throws UnknownHostException { final PeerMap peerMap = new PeerMap(conf); List peers = new ArrayList(); for (int i = 0; i < round; i++) { - PeerAddress r1 = new PeerAddress(new Number160(rnd)); + PeerAddress r1 = Utils2.createPeerAddress(new Number160(rnd)); peers.add(r1); peerMap.peerFound(r1, null, null, null); } diff --git a/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java b/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java index a4521628d..04c315642 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java +++ b/core/src/test/java/net/tomp2p/rpc/TestBloomFilter.java @@ -56,7 +56,7 @@ public void testEmptyBloomfilter() { Assert.assertEquals(false, bloomFilter.contains(hash)); // convert and back ByteBuf buf = Unpooled.buffer(SimpleBloomFilter.SIZE_HEADER); - bloomFilter.toByteBuf(buf); + bloomFilter.encode(buf); SimpleBloomFilter bloomFilter2 = new SimpleBloomFilter(buf); Assert.assertEquals(true, bloomFilter2.isVoid()); } @@ -69,7 +69,7 @@ public void testFullBloomfilter() { Assert.assertEquals(true, bloomFilter.contains(hash)); // convert and back, minimun size is a long ByteBuf buf = Unpooled.buffer(8 + SimpleBloomFilter.SIZE_HEADER); - bloomFilter.toByteBuf(buf); + bloomFilter.encode(buf); SimpleBloomFilter bloomFilter2 = new SimpleBloomFilter(buf); Assert.assertEquals(true, bloomFilter2.isFull()); } @@ -81,7 +81,7 @@ public void testOneBloomfilter1() { bloomFilter.add(hash); // convert and back, minimun size is a long ByteBuf buf = Unpooled.buffer(); - bloomFilter.toByteBuf(buf); + bloomFilter.encode(buf); SimpleBloomFilter bloomFilter2 = new SimpleBloomFilter(buf); Assert.assertEquals(true, bloomFilter2.contains(hash)); } @@ -93,7 +93,7 @@ public void testOneBloomfilter2() { bloomFilter.add(hash); // convert and back, minimun size is a long ByteBuf buf = Unpooled.buffer(); - bloomFilter.toByteBuf(buf); + bloomFilter.encode(buf); SimpleBloomFilter bloomFilter2 = new SimpleBloomFilter(buf); Assert.assertEquals(true, bloomFilter2.contains(hash)); } @@ -115,7 +115,7 @@ public void testBloomfilter() { // convert and back ByteBuf buf = Unpooled.buffer(filterSize + SimpleBloomFilter.SIZE_HEADER); - bloomFilter.toByteBuf(buf); + bloomFilter.encode(buf); SimpleBloomFilter bloomFilter2 = new SimpleBloomFilter(buf); Assert.assertEquals(true, bloomFilter2.contains(Number160.MAX_VALUE)); Assert.assertEquals(false, bloomFilter2.contains(Number160.ONE)); diff --git a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java index 6f10a8192..f7d682a88 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java +++ b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java @@ -77,8 +77,8 @@ public void testNeigbhor() throws Exception { // we are able to fit 40 neighbors into 1400 bytes Assert.assertEquals(33, pas.size()); Assert.assertEquals(new Number160("0x1"), pas.neighbors().iterator().next().peerId()); - Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().tcpPort()); - Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().udpPort()); + Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().ipv4Socket().tcpPort()); + Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().ipv4Socket().udpPort()); cc.shutdown(); } finally { if (sender != null) { @@ -122,8 +122,8 @@ public void testNeigbhorTCP() throws Exception { // we are able to fit 40 neighbors into 1400 bytes Assert.assertEquals(33, pas.size()); Assert.assertEquals(new Number160("0x1"), pas.neighbors().iterator().next().peerId()); - Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().tcpPort()); - Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().udpPort()); + Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().ipv4Socket().tcpPort()); + Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().ipv4Socket().udpPort()); cc.shutdown(); } finally { if (sender != null) { From d28bd153c76c6e7a246862e07e0ce81527792eb8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 3 Nov 2015 15:47:23 +0100 Subject: [PATCH 112/135] further ipv6 + udt fixes --- .../net/tomp2p/connection/Reservation.java | 2 +- .../main/java/net/tomp2p/message/Decoder.java | 13 +- .../main/java/net/tomp2p/message/Encoder.java | 4 +- .../tomp2p/message/MessageHeaderCodec.java | 7 +- .../net/tomp2p/message/TomP2POutbound.java | 30 ++-- .../tomp2p/p2p/builder/DiscoverBuilder.java | 2 +- core/src/main/java/net/tomp2p/peers/IP.java | 8 +- .../java/net/tomp2p/peers/PeerAddress.java | 98 ++++++++++++- .../java/net/tomp2p/peers/PeerIPFilter.java | 34 +++-- .../net/tomp2p/peers/PeerSocketAddress.java | 10 ++ core/src/test/java/net/tomp2p/Utils2.java | 2 +- .../tomp2p/connection/TestReservation.java | 2 +- .../java/net/tomp2p/message/TestMessage.java | 14 +- .../java/net/tomp2p/p2p/TestBootstrap.java | 4 +- .../test/java/net/tomp2p/p2p/TestDirect.java | 2 +- .../tomp2p/p2p/TestRTTRoutingComparator.java | 16 +-- .../java/net/tomp2p/rpc/TestNeighbor.java | 4 +- .../test/java/net/tomp2p/rpc/TestPing.java | 1 - .../java/net/tomp2p/rpc/TestRealPing.java | 6 +- core/src/test/resources/logback.xml | 5 + .../java/net/tomp2p/dht/TestRealNetwork.java | 134 ------------------ .../java/net/tomp2p/dht/TestStorageDHT.java | 8 +- .../test/java/net/tomp2p/dht/UtilsDHT2.java | 13 +- .../net/tomp2p/examples/ExampleBuffer.java | 2 +- .../tomp2p/examples/ExampleDirectData.java | 2 +- .../net/tomp2p/examples/ExampleDiscover.java | 2 +- .../net/tomp2p/examples/ExampleHoleP.java | 2 +- .../java/net/tomp2p/examples/ExampleNAT.java | 2 +- .../net/tomp2p/examples/ExampleNATChat.java | 2 +- .../net/tomp2p/examples/ExampleReconnect.java | 2 +- .../holep/strategy/AbstractHolePStrategy.java | 14 +- .../net/tomp2p/relay/DistributedRelay.java | 3 +- .../main/java/net/tomp2p/relay/Forwarder.java | 1 - .../java/net/tomp2p/relay/RelayUtils.java | 15 +- .../replication/SlowReplicationFilter.java | 2 +- .../src/test/java/net/tomp2p/Utils2.java | 5 +- .../net/tomp2p/tracker/TrackerStorage.java | 2 +- .../tomp2p/tracker/TestTrackerStorage.java | 16 +-- 38 files changed, 238 insertions(+), 253 deletions(-) delete mode 100644 dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index 00d3afa98..ccaba21df 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -464,7 +464,7 @@ public void run() { } else if(peerBean.serverPeerAddress().net4Internal()) { fromAddress = peerBean.serverPeerAddress().ipInternalSocket().ipv4().toInetAddress(); } else { - fromAddress = peerBean.serverPeerAddress().ipInternalSocket().ipv4().toInetAddress(); + fromAddress = peerBean.serverPeerAddress().ipv4Socket().ipv4().toInetAddress(); } LOG.debug("channel from {}", fromAddress); diff --git a/core/src/main/java/net/tomp2p/message/Decoder.java b/core/src/main/java/net/tomp2p/message/Decoder.java index a2d3bad9b..45226669d 100644 --- a/core/src/main/java/net/tomp2p/message/Decoder.java +++ b/core/src/main/java/net/tomp2p/message/Decoder.java @@ -52,7 +52,8 @@ public class Decoder { // private Message2 result = null; // current state - needs to be deleted if we want to reuse - private final Message message = new Message(); + private Message message = new Message(); + private boolean headerDone = false; private Signature signature = null; @@ -258,10 +259,10 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, neighborSet = new NeighborSet(-1, new ArrayList(neighborSize)); } for (int i = neighborSet.size(); i < neighborSize; i++) { - if (buf.readableBytes() < 4) { + if (buf.readableBytes() < PeerAddress.HEADER_SIZE) { return false; } - size = PeerAddress.size(buf.getInt(buf.readerIndex())); + size = PeerAddress.size(buf.getUnsignedMedium(buf.readerIndex())); if (buf.readableBytes() < size) { return false; } @@ -578,8 +579,9 @@ public boolean decodePayload(final ByteBuf buf) throws NoSuchAlgorithmException, } public Message prepareFinish() { - Message ret = message; - message.setDone(); + final Message ret = message; + message = new Message(); + ret.setDone(); contentTypes.clear(); headerDone = false; neighborSize = -1; @@ -614,6 +616,7 @@ public static void inheritPublicKey(Message message, Data data) { } public void release() { + if(message!=null) { message.release(); } diff --git a/core/src/main/java/net/tomp2p/message/Encoder.java b/core/src/main/java/net/tomp2p/message/Encoder.java index fb3f44ef0..008c00d95 100644 --- a/core/src/main/java/net/tomp2p/message/Encoder.java +++ b/core/src/main/java/net/tomp2p/message/Encoder.java @@ -37,13 +37,13 @@ public Encoder(SignatureFactory signatureFactory) { this.signatureFactory = signatureFactory; } - public boolean write(final AlternativeCompositeByteBuf buf, final Message message, SignatureCodec signatureCodec, boolean ipv6) throws InvalidKeyException, + public boolean write(final AlternativeCompositeByteBuf buf, final Message message, SignatureCodec signatureCodec) throws InvalidKeyException, SignatureException, IOException { this.message = message; LOG.debug("message for outbound {}", message); - MessageHeaderCodec.encodeHeader(buf, message, ipv6); + MessageHeaderCodec.encodeHeader(buf, message); boolean done = loop(buf); LOG.debug("message encoded {}", message); diff --git a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java index e15c7b517..8780b55e7 100644 --- a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java +++ b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java @@ -75,7 +75,7 @@ private MessageHeaderCodec() { * The message with the header that will be encoded * @return The buffer passed as an argument */ - public static void encodeHeader(final ByteBuf buf, final Message message, final boolean ipv6) { + public static void encodeHeader(final ByteBuf buf, final Message message) { final int versionAndType = message.version() << 4 | (message.type().ordinal() & Utils.MASK_0F); buf.writeInt(versionAndType); // 4 buf.writeInt(message.messageId()); // 8 @@ -84,8 +84,7 @@ public static void encodeHeader(final ByteBuf buf, final Message message, final buf.writeInt(encodeContentTypes(message.contentTypes())); // 33 // three bits for the message options, 5 bits for the sender options buf.writeByte(message.options()); // 34 - final PeerAddress sender = ipv6 ? message.sender().withSkipIPv6(true) : message.sender().withSkipIPv4(true); - sender.encode(buf); + message.sender().encode(buf); } /** @@ -124,7 +123,7 @@ public static boolean decodeHeader(final ByteBuf buffer, final InetSocketAddress final int header = buffer.readUnsignedMedium(); final int peerAddressSize = PeerAddress.size(header); - if(buffer.readableBytes() < peerAddressSize) { + if(3 + buffer.readableBytes() < peerAddressSize) { return false; } PeerAddress peerAddress = PeerAddress.decode(header, buffer); diff --git a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java index d4732421a..09a418936 100644 --- a/core/src/main/java/net/tomp2p/message/TomP2POutbound.java +++ b/core/src/main/java/net/tomp2p/message/TomP2POutbound.java @@ -1,5 +1,11 @@ package net.tomp2p.message; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -7,17 +13,10 @@ import io.netty.channel.ChannelPromise; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.DatagramPacket; - -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; - import net.tomp2p.connection.SignatureFactory; +import net.tomp2p.peers.PeerAddress; import net.tomp2p.storage.AlternativeCompositeByteBuf; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class TomP2POutbound extends ChannelOutboundHandlerAdapter { private static final Logger LOG = LoggerFactory.getLogger(TomP2POutbound.class); @@ -37,14 +36,13 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann ctx.write(msg, promise); return; } - boolean ipv6 = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress() instanceof Inet6Address; - + try { boolean done = false; buf = AlternativeCompositeByteBuf.compBuffer(byteBufAllocator, buf); //null, means create signature, as we did not have created one already - done = encoder.write(buf, (Message) msg, null, ipv6); + done = encoder.write(buf, (Message) msg, null); final Message message = encoder.message(); @@ -52,20 +50,22 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann // this will release the buffer if (ctx.channel() instanceof DatagramChannel) { + final PeerAddress recipientAddress; InetSocketAddress recipient; InetSocketAddress sender; if (message.senderSocket() == null) { //in case of a request if(message.recipientRelay()!=null) { //in case of sending to a relay (the relayed flag is already set) - recipient = ipv6 ? message.recipientRelay().ipv6Socket().createUDPSocket(): message.recipientRelay().ipv4Socket().createUDPSocket(); + recipientAddress = message.recipientRelay(); } else if(message.recipientReflected()!=null) { //in case we use nat reflection - recipient = ipv6 ? message.recipientReflected().ipv6Socket().createUDPSocket() : message.recipientReflected().ipv4Socket().createUDPSocket(); + recipientAddress = message.recipientReflected(); } else { - recipient = ipv6 ? message.recipient().ipv6Socket().createUDPSocket() : message.recipient().ipv4Socket().createUDPSocket(); + recipientAddress = message.recipient(); } - sender = ipv6 ? message.sender().ipv6Socket().createSocket(0) : message.sender().ipv4Socket().createSocket(0); + recipient = recipientAddress.createUDPSocket(message.sender()); + sender = message.sender().createSocket(recipientAddress, 0) ; } else { //in case of a reply recipient = message.senderSocket(); diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 906414606..6c02eae50 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -222,7 +222,7 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio */ private void discover(final FutureDiscover futureDiscover, final PeerAddress peerAddress, final ChannelCreator cc, final ConnectionConfiguration configuration) { - + LOG.debug("starting discover to {}",peerAddress); final FutureDone pingDone = new FutureDone(); peer.pingRPC().addPeerReachableListener(new PeerReachable() { diff --git a/core/src/main/java/net/tomp2p/peers/IP.java b/core/src/main/java/net/tomp2p/peers/IP.java index 89de34d04..9cb03e6e3 100644 --- a/core/src/main/java/net/tomp2p/peers/IP.java +++ b/core/src/main/java/net/tomp2p/peers/IP.java @@ -83,13 +83,13 @@ public int hashCode() { @Override public String toString() { final StringBuilder sb = new StringBuilder("/"); - sb.append((byte) (bits >>> 24)); + sb.append((bits >>> 24) & 0xff); sb.append('.'); - sb.append((byte) (bits >>> 16)); + sb.append((bits >>> 16) & 0xff); sb.append('.'); - sb.append((byte) (bits >>> 8)); + sb.append((bits >>> 8) & 0xff ); sb.append('.'); - sb.append((byte) bits); + sb.append(bits & 0xff); return sb.toString(); } } diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 23995e42f..2339001cf 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -16,6 +16,10 @@ package net.tomp2p.peers; import java.io.Serializable; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; @@ -140,6 +144,12 @@ public final class PeerAddress implements Comparable, Serializable public static final Collection EMPTY_PEER_SOCKET_ADDRESSES = Collections.emptySet(); public static final byte EMPTY_RELAY_TYPES = 0; + public static final boolean preferIPv6Addresses; + + static { + preferIPv6Addresses = "true".equalsIgnoreCase(System.getProperty("java.net.preferIPv6Addresses")); + } + //Change lomboks default behavior public static class PeerAddressBuilder { public PeerAddressBuilder relay(PeerSocketAddress relay) { @@ -545,7 +555,7 @@ public String toString() { sb.append('}'); sb.append("r:").append(relaySize).append("("); - for(final PeerSocketAddress relay:relays) { + for(final PeerSocketAddress relay:relays()) { sb.append(relay); } sb.append(')'); @@ -599,6 +609,92 @@ public PeerAddress withIPSocket(PeerSocketAddress ps) { } } + public static PeerAddress create(final Number160 peerId) { + return builder().peerId(peerId).build(); + } + + public static PeerAddress create(final Number160 peerId, String host, int udpPort, int tcpPort, int udtPort) throws UnknownHostException { + return create(peerId, InetAddress.getByName(host), udpPort, tcpPort, udtPort); + } + + public static PeerAddress create(final Number160 peerId, InetAddress inet, int port) { + return create(peerId, inet, port, port, port + 1); + } + + public static PeerAddress create(final Number160 peerId, InetSocketAddress inetSocket) { + return create(peerId, inetSocket.getAddress(), inetSocket.getPort(), inetSocket.getPort(), inetSocket.getPort() + 1); + } + + public static PeerAddress create(final Number160 peerId, InetAddress inet, int udpPort, int tcpPort, int udtPort) { + if(inet instanceof Inet4Address) { + final PeerSocket4Address ps4a = PeerSocket4Address.builder() + .ipv4(IP.IPv4.fromInet4Address(inet)) + .udpPort(udpPort) + .tcpPort(tcpPort) + .udtPort(udtPort) + .build(); + return builder() + .peerId(peerId) + .ipv4Socket(ps4a) + .build(); + } else { + final PeerSocket6Address ps6a = PeerSocket6Address.builder() + .ipv6(IP.IPv6.fromInet6Address(inet)) + .udpPort(udpPort) + .tcpPort(tcpPort) + .udtPort(udtPort) + .build(); + return builder() + .peerId(peerId) + .ipv6Socket(ps6a) + .build(); + } + } + + + + public InetSocketAddress createUDPSocket(final PeerAddress sender) { + final boolean canIPv6 = ipv6Flag && sender.ipv6Flag; + final boolean canIPv4 = ipv4Flag && sender.ipv4Flag; + if((preferIPv6Addresses && canIPv6) || + (!canIPv4 && canIPv6)) { + if(ipv6Socket == null) { + throw new RuntimeException("Flag indicates that ipv6 is present, but its not"); + } + return ipv6Socket.createUDPSocket(); + } else if(canIPv4) { + if(ipv4Socket == null) { + throw new RuntimeException("Flag indicates that ipv4 is present, but its not"); + } + return ipv4Socket.createUDPSocket(); + } + else { + throw new RuntimeException("No matching protocal found"); + } + } + + + + public InetSocketAddress createSocket(final PeerAddress recipient, final int port) { + final boolean canIPv6 = ipv6Flag && recipient.ipv6Flag; + final boolean canIPv4 = ipv4Flag && recipient.ipv4Flag; + if((preferIPv6Addresses && canIPv6) || + (!canIPv4 && canIPv6)) { + if(ipv6Socket == null) { + throw new RuntimeException("Flag indicates that ipv6 is present, but its not"); + } + return ipv6Socket.createSocket(port); + } else if(canIPv4) { + if(ipv4Socket == null) { + throw new RuntimeException("Flag indicates that ipv4 is present, but its not"); + } + return ipv4Socket.createSocket(port); + } + else { + throw new RuntimeException("No matching protocal found"); + } + } + /*private int prefix4(InetAddress inetAddress) { NetworkInterface networkInterface; try { diff --git a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java index 64c0b1cc5..e5658fa24 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java +++ b/core/src/main/java/net/tomp2p/peers/PeerIPFilter.java @@ -18,6 +18,9 @@ import java.util.Collection; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; + /** * Filter peers if the IP is the same. Being too strict does not mean to harm * the network. Other peers will have the information about the peer even if you @@ -44,21 +47,30 @@ public boolean rejectPeerMap(final PeerAddress peerAddress, final PeerMap peerMa @Override public boolean rejectPreRouting(final PeerAddress peerAddress, final Collection all) { - final IP.IPv4 ipv4 = peerAddress.ipv4Socket().ipv4(); - for (final PeerAddress inMap : all) { - final IP.IPv4 ipv4Test = inMap.ipv4Socket().ipv4(); - if (ipv4.maskWithNetworkMask(mask4).equals(ipv4Test.maskWithNetworkMask(mask4))) { - return true; + if(peerAddress.ipv4Socket() != null) { + final IP.IPv4 ipv4 = peerAddress.ipv4Socket().ipv4(); + for (final PeerAddress inMap : all) { + final PeerSocket4Address ps4a = inMap.ipv4Socket(); + if(ps4a == null) { + continue; + } + if (ipv4.maskWithNetworkMask(mask4).equals(ps4a.ipv4().maskWithNetworkMask(mask4))) { + return true; + } } } - final IP.IPv6 ipv6 = peerAddress.ipv6Socket().ipv6(); - for (final PeerAddress inMap : all) { - final IP.IPv6 ipv6Test = inMap.ipv6Socket().ipv6(); - if (ipv6.maskWithNetworkMask(mask6).equals(ipv6Test.maskWithNetworkMask(mask6))) { - return true; + if(peerAddress.ipv6Socket() != null) { + final IP.IPv6 ipv6 = peerAddress.ipv6Socket().ipv6(); + for (final PeerAddress inMap : all) { + final PeerSocket6Address ps6a = inMap.ipv6Socket(); + if(ps6a == null) { + continue; + } + if (ipv6.maskWithNetworkMask(mask6).equals(ps6a.ipv6().maskWithNetworkMask(mask6))) { + return true; + } } - } return false; diff --git a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java index fb381cc53..4cf48b101 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java @@ -1,5 +1,7 @@ package net.tomp2p.peers; +import java.net.Inet4Address; +import java.net.InetAddress; import java.net.InetSocketAddress; import io.netty.buffer.ByteBuf; @@ -331,4 +333,12 @@ public InetSocketAddress createTCPSocket() { } } + public static PeerSocketAddress create(InetAddress inet, int udpPort, int tcpPort, int udtPort) { + if(inet instanceof Inet4Address) { + return PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inet)).udpPort(udpPort).tcpPort(tcpPort).udtPort(udtPort).build(); + } else { + return PeerSocket6Address.builder().ipv6(IPv6.fromInet6Address(inet)).udpPort(udpPort).tcpPort(tcpPort).udtPort(udtPort).build(); + } + + } } diff --git a/core/src/test/java/net/tomp2p/Utils2.java b/core/src/test/java/net/tomp2p/Utils2.java index dd5c24599..03fb94f23 100644 --- a/core/src/test/java/net/tomp2p/Utils2.java +++ b/core/src/test/java/net/tomp2p/Utils2.java @@ -78,7 +78,7 @@ public static Message createDummyMessage(Number160 idSender, String inetSender, Message message = new Message(); PeerAddress n1 = createAddress(idSender, inetSender, tcpPortSender, udpPortSender, firewallUDP, firewallTCP); - message.sender(n1); + message.sender(n1.withSkipIPv4(true)); // PeerAddress n2 = createAddress(idRecipient, inetRecipient, tcpPortRecipient, udpPortRecipient, firewallUDP, firewallTCP); diff --git a/core/src/test/java/net/tomp2p/connection/TestReservation.java b/core/src/test/java/net/tomp2p/connection/TestReservation.java index 210b56a88..c6d6d3104 100644 --- a/core/src/test/java/net/tomp2p/connection/TestReservation.java +++ b/core/src/test/java/net/tomp2p/connection/TestReservation.java @@ -86,7 +86,7 @@ public void createSink() throws IOException { Bindings bindings = new Bindings().addAddress(InetAddress.getByName("127.0.0.1")); ChannelServerConfiguration c = new ChannelServerConfiguration(); c.bindings(bindings); - c.ports(new Ports(PORT, PORT)); + c.ports(new Ports(PORT, PORT, PORT + 1)); c.pipelineFilter(new MyPipeLine()); final EventLoopGroup bossGroup = new NioEventLoopGroup(0, new DefaultThreadFactory(ConnectionBean.THREAD_NAME + "boss - ")); diff --git a/core/src/test/java/net/tomp2p/message/TestMessage.java b/core/src/test/java/net/tomp2p/message/TestMessage.java index b3ba01905..7976d7c4f 100644 --- a/core/src/test/java/net/tomp2p/message/TestMessage.java +++ b/core/src/test/java/net/tomp2p/message/TestMessage.java @@ -470,10 +470,10 @@ public void serializationTest() throws IOException, ClassNotFoundException, m1.buffer(new Buffer(Unpooled.buffer())); Encoder e = new Encoder(null); AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); - e.write(buf, m1, null, true); + e.write(buf, m1, null); Decoder d = new Decoder(null); - boolean header = d.decodeHeader(buf, new InetSocketAddress(0), - new InetSocketAddress(0)); + boolean header = d.decodeHeader(buf, m1.recipient().ipv4Socket().createTCPSocket(), + m1.sender().ipv4Socket().createTCPSocket()); boolean payload = d.decodePayload(buf); Assert.assertEquals(true, header); Assert.assertEquals(true, payload); @@ -621,7 +621,6 @@ public void testInternalPeerSocket() throws Exception { @Test public void testSlowFlag() throws Exception { // encode Message m1 = Utils2.createDummyMessage(); - m1.sender(m1.sender().withSlow(true)); Message m2 = encodeDecode(m1); m1.sender(m1.sender().withSkipIPv4(true)); @@ -649,8 +648,11 @@ public void testSize() throws Exception { message.intValue(-1); message.longValue(9l); + + Message m2 = encodeDecode(message); + message.sender(message.sender().withSkipIPv4(true)); int size = message.estimateSize(); - Assert.assertEquals(size, encodeDecode(message).estimateSize()); + Assert.assertEquals(size, m2.estimateSize()); } /** @@ -665,7 +667,7 @@ private Message encodeDecode(final Message m1) throws Exception { AtomicReference m2 = new AtomicReference(); final AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); Encoder encoder = new Encoder(new DSASignatureFactory()); - encoder.write(buf, m1, null, false); + encoder.write(buf, m1, null); ChannelHandlerContext ctx = mockChannelHandlerContext(buf, m2); Decoder decoder = new Decoder(new DSASignatureFactory()); decoder.decode(ctx, buf, m1.recipient().ipv4Socket().createTCPSocket(), m1 diff --git a/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java b/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java index 3e854e1f6..d934de97f 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java +++ b/core/src/test/java/net/tomp2p/p2p/TestBootstrap.java @@ -147,7 +147,7 @@ public void testBootstrap5() throws Exception { Peer peer = null; try { peer = new PeerBuilder(new Number160(rnd)).ports(4000).start(); - PeerAddress pa = new PeerAddress(new Number160(rnd), "192.168.77.77", 4000, 4000); + PeerAddress pa = PeerAddress.create(new Number160(rnd), "192.168.77.77", 4000, 4000, 4001); FutureBootstrap tmp = peer.bootstrap().peerAddress(pa).start(); tmp.awaitUninterruptibly(); Assert.assertEquals(false, tmp.isSuccess()); @@ -193,7 +193,7 @@ public void testBootstrap7() throws Exception { peer = new PeerBuilder(new Number160(rnd)).ports(4000).start(); Collection bootstrapTo = new ArrayList(2); - PeerAddress pa = new PeerAddress(new Number160(rnd), "192.168.77.77", 4000, 4000); + PeerAddress pa = PeerAddress.create(new Number160(rnd), "192.168.77.77", 4000, 4000, 4001); bootstrapTo.add(peer.peerAddress()); bootstrapTo.add(pa); FutureBootstrap tmp = peer.bootstrap().bootstrapTo(bootstrapTo).start(); diff --git a/core/src/test/java/net/tomp2p/p2p/TestDirect.java b/core/src/test/java/net/tomp2p/p2p/TestDirect.java index 1da101877..c31cde2b4 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestDirect.java +++ b/core/src/test/java/net/tomp2p/p2p/TestDirect.java @@ -34,7 +34,7 @@ public void testDirectMessage1() throws Exception { recv1.objectDataReply(new ObjectDataReply() { @Override public Object reply(PeerAddress sender, Object request) throws Exception { - System.err.println(sender.inetAddress()); + System.err.println(sender); return "yes"; } }); diff --git a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java index 8115a55ed..6a05b5648 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java +++ b/core/src/test/java/net/tomp2p/p2p/TestRTTRoutingComparator.java @@ -39,9 +39,9 @@ protected void starting(Description description) { */ @Test public void testEquality() { - PeerAddress peer1 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); + PeerAddress peer1 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); PeerStatistic peer1Statistic = new PeerStatistic(peer1).addRTT(new RTT(13, false).setEstimated()); - PeerAddress peer2 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); + PeerAddress peer2 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); PeerStatistic peer2Statistic = new PeerStatistic(peer2).addRTT(new RTT(44, true)); Comparator comp = new RTTPeerStatisticComparator().getComparator(new Number160("0xfff")); @@ -56,9 +56,9 @@ public void testEquality() { */ @Test public void testUnequality() { - PeerAddress peer1 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c61")); + PeerAddress peer1 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c61")); PeerStatistic peer1Statistic = new PeerStatistic(peer1).addRTT(new RTT(44, true)); - PeerAddress peer2 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c62")); + PeerAddress peer2 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c62")); PeerStatistic peer2Statistic = new PeerStatistic(peer2).addRTT(new RTT(44, true)); Comparator comp = new RTTPeerStatisticComparator().getComparator(new Number160("0xfff")); @@ -77,10 +77,10 @@ public void testQueueToAskOrder() { Number160 location = new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c40"); // 4 Peers with different (bucket)distances to location - PeerAddress peer1 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); - PeerAddress peer2 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982000000000000")); - PeerAddress peer3 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982700000000000")); - PeerAddress peer4 = new PeerAddress(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c70")); + PeerAddress peer1 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c60")); + PeerAddress peer2 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982000000000000")); + PeerAddress peer3 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982700000000000")); + PeerAddress peer4 = PeerAddress.create(new Number160("0xa3fb3982c38193f12c40a3fb3982c38193f12c70")); // Test all bucket distances to location (this will be the first sorting criteria) Assert.assertEquals(6, PeerMap.classMember(peer1.peerId(), location) + 1); diff --git a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java index f7d682a88..f84bbdcc6 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java +++ b/core/src/test/java/net/tomp2p/rpc/TestNeighbor.java @@ -75,7 +75,7 @@ public void testNeigbhor() throws Exception { Assert.assertEquals(true, fr.isSuccess()); NeighborSet pas = fr.responseMessage().neighborsSet(0); // we are able to fit 40 neighbors into 1400 bytes - Assert.assertEquals(33, pas.size()); + Assert.assertEquals(30, pas.size()); Assert.assertEquals(new Number160("0x1"), pas.neighbors().iterator().next().peerId()); Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().ipv4Socket().tcpPort()); Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().ipv4Socket().udpPort()); @@ -120,7 +120,7 @@ public void testNeigbhorTCP() throws Exception { Assert.assertEquals(true, fr.isSuccess()); NeighborSet pas = fr.responseMessage().neighborsSet(0); // we are able to fit 40 neighbors into 1400 bytes - Assert.assertEquals(33, pas.size()); + Assert.assertEquals(30, pas.size()); Assert.assertEquals(new Number160("0x1"), pas.neighbors().iterator().next().peerId()); Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().ipv4Socket().tcpPort()); Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().ipv4Socket().udpPort()); diff --git a/core/src/test/java/net/tomp2p/rpc/TestPing.java b/core/src/test/java/net/tomp2p/rpc/TestPing.java index 860198730..07477f502 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestPing.java +++ b/core/src/test/java/net/tomp2p/rpc/TestPing.java @@ -415,7 +415,6 @@ public void testPingTime() throws Exception { new DefaultConnectionConfiguration()); list.add(fr); } - int ii = 0; for (FutureResponse fr2 : list) { fr2.awaitUninterruptibly(); Assert.assertEquals(true, fr2.isSuccess()); diff --git a/core/src/test/java/net/tomp2p/rpc/TestRealPing.java b/core/src/test/java/net/tomp2p/rpc/TestRealPing.java index 4d7cfc4ad..9e5979077 100644 --- a/core/src/test/java/net/tomp2p/rpc/TestRealPing.java +++ b/core/src/test/java/net/tomp2p/rpc/TestRealPing.java @@ -73,7 +73,7 @@ public void sendPingTCP() throws IOException, InterruptedException { Peer sender = null; ChannelCreator cc = null; try { - PeerAddress pa = new PeerAddress(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT); + PeerAddress pa = PeerAddress.create(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT, PORT+1); sender = new PeerBuilder(new Number160("0x9876")).ports(PORT).enableMaintenance(false) .start(); PingRPC handshake = new PingRPC(sender.peerBean(), sender.connectionBean()); @@ -107,7 +107,7 @@ public void sendPingTCPDiscover() throws IOException, InterruptedException { Peer sender = null; ChannelCreator cc = null; try { - PeerAddress pa = new PeerAddress(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT); + PeerAddress pa = PeerAddress.create(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT, PORT + 1); sender = new PeerBuilder(new Number160("0x9876")).ports(PORT).enableMaintenance(false) .start(); PingRPC handshake = new PingRPC(sender.peerBean(), sender.connectionBean()); @@ -141,7 +141,7 @@ public void sendPingTCPProbe() throws IOException, InterruptedException { Peer sender = null; ChannelCreator cc = null; try { - PeerAddress pa = new PeerAddress(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT); + PeerAddress pa = PeerAddress.create(Number160.ZERO, Inet4Address.getByName(IP), PORT, PORT, PORT + 1); sender = new PeerBuilder(new Number160("0x9876")).ports(PORT).enableMaintenance(false) .start(); PingRPC handshake = new PingRPC(sender.peerBean(), sender.connectionBean()); diff --git a/core/src/test/resources/logback.xml b/core/src/test/resources/logback.xml index 641782236..997001a56 100644 --- a/core/src/test/resources/logback.xml +++ b/core/src/test/resources/logback.xml @@ -17,6 +17,11 @@ + + + + + diff --git a/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java b/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java deleted file mode 100644 index 987967292..000000000 --- a/dht/src/test/java/net/tomp2p/dht/TestRealNetwork.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2012 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.dht; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; - -import net.tomp2p.futures.FutureBootstrap; -import net.tomp2p.futures.FutureDiscover; -import net.tomp2p.p2p.Peer; -import net.tomp2p.p2p.PeerBuilder; -import net.tomp2p.peers.Number160; -import net.tomp2p.peers.PeerAddress; -import net.tomp2p.storage.Data; - -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TestRule; -import org.junit.rules.TestWatcher; -import org.junit.runner.Description; - -/** - * Tests over a real network. Since this requires a real network, the tests are - * not based on JUnit. - * - * @author Thomas Bocek - */ -public class TestRealNetwork { - private final int port = 4000; - - private final String ipSuperPeer = "192.168.1.187"; - - @Rule - public TestRule watcher = new TestWatcher() { - protected void starting(Description description) { - System.out.println("Starting test: " + description.getMethodName()); - } - }; - - /** - * Starts the super peer. - * - * @throws IOException - * PeerMaker may throw and IOException - * @throws InterruptedException . - */ - @Test - @Ignore - public void startSuperPeer() throws IOException, InterruptedException { - new PeerBuilder(Number160.createHash("super peer")).ports(port).start(); - Thread.sleep(Long.MAX_VALUE); - } - - /** - * Tests multiple connect and disconnects. - * - * @throws ClassNotFoundException . - * @throws IOException . - * @throws InterruptedException . - */ - @Test - @Ignore - public void startClient2() throws ClassNotFoundException, IOException, InterruptedException { - final int nrClients = 1000; - for (int i = 0; i < nrClients; i++) { - startClient(); - } - } - - /** - * Starts the client peer. - * - * @throws IOException - * PeerMaker may throw and IOException - * @throws ClassNotFoundException - * If the data object contained a class we did not expect - * @throws InterruptedException . - */ - @Test - @Ignore - public void startClient() throws IOException, ClassNotFoundException, InterruptedException { - Peer myPeer = new PeerBuilder(Number160.createHash("client peer")).behindFirewall(true). - ports(port).enableMaintenance(false).start(); - PeerAddress bootstrapServerPeerAddress = new PeerAddress(Number160.ZERO, new InetSocketAddress( - InetAddress.getByName(ipSuperPeer), port)); - - FutureDiscover discovery = myPeer.discover().peerAddress(bootstrapServerPeerAddress).start(); - discovery.awaitUninterruptibly(); - if (!discovery.isSuccess()) { - System.err.println("no success!"); - } - System.err.println("Peer: " + discovery.reporter() + " told us about our address."); - InetSocketAddress myInetSocketAddress = new InetSocketAddress(myPeer.peerAddress().inetAddress(), port); - - bootstrapServerPeerAddress = discovery.reporter(); - FutureBootstrap bootstrap = myPeer.bootstrap().peerAddress(bootstrapServerPeerAddress).start(); - bootstrap.awaitUninterruptibly(); - - if (!bootstrap.isSuccess()) { - System.err.println("no success!"); - } - - PeerDHT myPeerDHT = new PeerBuilderDHT(myPeer).start(); - - FuturePut putFuture = myPeerDHT.put(Number160.createHash("key")).data(new Data(myInetSocketAddress)).start(); - putFuture.awaitUninterruptibly(); - FutureGet futureDHT = myPeerDHT.get(Number160.createHash("key")).start(); - futureDHT.awaitUninterruptibly(); - futureDHT.futureRequests().awaitUninterruptibly(); - Data data = futureDHT.data(); - if (data == null) { - throw new RuntimeException("Address not available in DHT."); - } - InetSocketAddress inetSocketAddress = (InetSocketAddress) data.object(); - System.err.println("returned " + inetSocketAddress); - myPeer.shutdown(); - // Thread.sleep( Long.MAX_VALUE ); - } -} diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index 73735133c..87284f8a8 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -94,7 +94,7 @@ public void testNeigbhorBloomfilter() throws Exception { PeerDHT recv1 = null; try { sender = new PeerBuilderDHT(new PeerBuilder(new Number160("0x50")).p2pId(55).ports(2424).start()).start(); - PeerAddress[] pa = UtilsDHT2.createDummyAddress(300, PORT_TCP, PORT_UDP); + PeerAddress[] pa = UtilsDHT2.createDummyAddress(300, PORT_TCP, PORT_UDP, PORT_UDP + 1); for (int i = 0; i < pa.length; i++) { sender.peerBean().peerMap().peerFound(pa[i], null, null, null); } @@ -122,11 +122,11 @@ public void testNeigbhorBloomfilter() throws Exception { Assert.assertEquals(true, fr.isSuccess()); NeighborSet pas = fr.responseMessage().neighborsSet(0); // we are able to fit 40 neighbors into 1400 bytes - Assert.assertEquals(33, pas.size()); + Assert.assertEquals(30, pas.size()); Assert.assertEquals(10, (int) fr.responseMessage().intAt(0)); Assert.assertEquals(new Number160("0x1"), pas.neighbors().iterator().next().peerId()); - Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().tcpPort()); - Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().udpPort()); + Assert.assertEquals(PORT_TCP, pas.neighbors().iterator().next().ipv4Socket().tcpPort()); + Assert.assertEquals(PORT_UDP, pas.neighbors().iterator().next().ipv4Socket().udpPort()); cc.shutdown(); } finally { if (sender != null) { diff --git a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java index 313e8a17e..c119b37a5 100644 --- a/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java +++ b/dht/src/test/java/net/tomp2p/dht/UtilsDHT2.java @@ -40,7 +40,6 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress2; public class UtilsDHT2 { /** @@ -82,9 +81,7 @@ public static PeerAddress createAddress(String id) throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false,false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); + PeerAddress n1 = PeerAddress.create(idSender, inetSend, tcpPortSender, udpPortSender, udpPortSender + 1); return n1; } @@ -345,18 +342,18 @@ public static PeerAddress createAddressIP(String inet) throws UnknownHostExcepti return createAddress(Number160.createHash(inet), inet, 8005, 8006, false, false); } - public static PeerAddress[] createDummyAddress(int size, int portTCP, int portUDP) throws UnknownHostException { + public static PeerAddress[] createDummyAddress(int size, int portUDP, int portTCP, int portUDT) throws UnknownHostException { PeerAddress[] pa = new PeerAddress[size]; for (int i = 0; i < size; i++) { - pa[i] = createAddress(i + 1, portTCP, portUDP); + pa[i] = createAddress(i + 1, portUDP, portTCP, portUDT); } return pa; } - public static PeerAddress createAddress(int iid, int portTCP, int portUDP) throws UnknownHostException { + public static PeerAddress createAddress(int iid, int portUDP, int portTCP, int portUDT) throws UnknownHostException { Number160 id = new Number160(iid); InetAddress address = InetAddress.getByName("127.0.0.1"); - return new PeerAddress(id, address, portTCP, portUDP); + return PeerAddress.create(id, address, portUDP, portTCP, portUDT); } } diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java index 6adf12556..6f35431e4 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleBuffer.java @@ -29,7 +29,7 @@ public static void main(String[] args) throws Exception { PeerNAT pn2 = new PeerBuilderNAT(requester.peer()).bufferTimeoutSeconds(30).start(); PeerAddress pa = slow.peerBean().serverPeerAddress(); - pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true).changeSlow(true); + pa = pa.withSlow(true).withUnreachable(true); slow.peerBean().serverPeerAddress(pa); // find neighbors diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleDirectData.java b/examples/src/main/java/net/tomp2p/examples/ExampleDirectData.java index 654bd6856..948f34f9a 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleDirectData.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleDirectData.java @@ -24,7 +24,7 @@ public static void main(String[] args) throws IOException { PeerDHT p1 = new PeerBuilderDHT(new PeerBuilder(idP1).ports(1234).start()).start(); PeerDHT p2 = new PeerBuilderDHT(new PeerBuilder(idP2).ports(1235).start()).start(); BootstrapBuilder b = p2.peer().bootstrap(); - b.bootstrapTo(Arrays.asList(new PeerAddress(idP1, "localhost", 1234, 1234))); + b.bootstrapTo(Arrays.asList(PeerAddress.create(idP1, "localhost", 1234, 1234, 1235))); b.start().awaitUninterruptibly(); p1.peer().objectDataReply(new ObjectDataReply() { diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleDiscover.java b/examples/src/main/java/net/tomp2p/examples/ExampleDiscover.java index ab5c1ae7f..8154f7361 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleDiscover.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleDiscover.java @@ -75,7 +75,7 @@ public static void startClient(String ipAddress) throws Exception { InetAddress address = Inet4Address.getByName(ipAddress); int masterPort = 4000; - PeerAddress pa = new PeerAddress(Number160.ZERO, address, masterPort, masterPort); + PeerAddress pa = PeerAddress.create(Number160.ZERO, address, masterPort, masterPort, masterPort +1 ); System.out.println("PeerAddress: " + pa); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java b/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java index 71dbc2331..b10ee32bc 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleHoleP.java @@ -86,7 +86,7 @@ public static Peer setUpRelayingWithNewPeer() throws IOException, InterruptedExc // Bootstrap natpeer Peer unreachable = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORT + 1).start(); PeerAddress pa = unreachable.peerBean().serverPeerAddress(); - pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true); + pa = pa.withUnreachable(true).withSlow(true); unreachable.peerBean().serverPeerAddress(pa); // find neighbors diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java b/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java index 6a436205a..76050a632 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleNAT.java @@ -88,7 +88,7 @@ public void onShutdown() { System.out.println("shutdown"); } }).start(); - final PeerAddress pa = new PeerAddress(Number160.ZERO, InetAddress.getByName(ip), PORT_SERVER, PORT_SERVER); + final PeerAddress pa = PeerAddress.create(Number160.ZERO, InetAddress.getByName(ip), PORT_SERVER, PORT_SERVER, PORT_SERVER + 1); final FutureDiscover fd = peer.discover().peerAddress(pa).start(); final FutureNAT fn = peerNAT.portForwarding(fd); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleNATChat.java b/examples/src/main/java/net/tomp2p/examples/ExampleNATChat.java index 266d5ea50..fe138e6ef 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleNATChat.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleNATChat.java @@ -65,7 +65,7 @@ public static void main(String[] args) throws Exception { public static void startClientNAT(String ip) throws Exception { Random r = new Random(43L); PeerDHT peer = new PeerBuilderDHT(new PeerBuilder(new Number160(r)).ports(clientPort).behindFirewall().start()).start(); - PeerAddress bootStrapServer = new PeerAddress(Number160.ZERO, InetAddress.getByName(ip), serverPort, serverPort); + PeerAddress bootStrapServer = PeerAddress.create(Number160.ZERO, InetAddress.getByName(ip), serverPort, serverPort, serverPort + 1); FutureDiscover fd = peer.peer().discover().peerAddress(bootStrapServer).start(); System.out.println("About to wait..."); fd.awaitUninterruptibly(); diff --git a/examples/src/main/java/net/tomp2p/examples/ExampleReconnect.java b/examples/src/main/java/net/tomp2p/examples/ExampleReconnect.java index 766b0e57c..f4d355155 100644 --- a/examples/src/main/java/net/tomp2p/examples/ExampleReconnect.java +++ b/examples/src/main/java/net/tomp2p/examples/ExampleReconnect.java @@ -24,7 +24,7 @@ public static void main(String[] args) throws IOException, InterruptedException } else { final Peer peer = new PeerBuilder(Number160.createHash("client")).ports(1235).start(); List bootstrap = new ArrayList(); - bootstrap.add(new PeerAddress(Number160.createHash("master"), "localhost", 1234,1234)); + bootstrap.add(PeerAddress.create(Number160.createHash("master"), "localhost", 1234, 1234, 1235)); peer.bootstrap().bootstrapTo(bootstrap).start(); peer.objectDataReply(new ObjectDataReply() { diff --git a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java index bb8675b49..2e386c445 100644 --- a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java +++ b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java @@ -29,7 +29,7 @@ import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.utils.Pair; @@ -289,7 +289,7 @@ public void tryConnect() throws Exception { for (int i = 0; i < channelFutures.size(); i++) { final Message dummyMessage = createDummyMessage(i); final FutureResponse futureResponse = new FutureResponse(dummyMessage); - LOG.debug("FIRE! remotePort: " + dummyMessage.recipient().udpPort() + ", localPort: " + dummyMessage.sender().udpPort()); + LOG.debug("FIRE! remote: {}, local: {}", dummyMessage.recipient(), dummyMessage.sender()); peer.connectionBean().sender().afterConnect(futureResponse, dummyMessage, channelFutures.get(i), FIRE_AND_FORGET_VALUE); } } @@ -458,11 +458,11 @@ protected synchronized void channelRead0(final ChannelHandlerContext ctx, final mainFutureDone.done(msg); ctx.close(); } else if (Message.Type.REQUEST_3 == msg.type() && Commands.HOLEP.getNr() == msg.command()) { - LOG.debug("Holes successfully punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " - + msg.sender().udpPort() + "}!"); + LOG.debug("Holes successfully punched with ports = {local = " + msg.recipient() + " , remote = " + + msg.sender() + "}!"); } else { - LOG.debug("Holes punche not punched with ports = {localPort = " + msg.recipient().udpPort() + " , remotePort = " - + msg.sender().udpPort() + "} yet!"); + LOG.debug("Holes punche not punched with ports = {local = " + msg.recipient() + " , remote = " + + msg.sender() + "} yet!"); } } }; @@ -582,7 +582,7 @@ private Message createSendOriginalMessage(final int localPort, final int remoteP */ private FutureDone createInitMessage(final List channelFutures) throws Exception { final FutureDone initMessageFutureDone = new FutureDone(); - final PeerSocketAddress2 socketAddress = Utils.extractRandomRelay(originalMessage); + final PeerSocketAddress socketAddress = Utils.extractRandomRelay(originalMessage); // we need to make a copy of the original Message final PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index 8193f626e..b01218a9e 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -25,7 +25,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMapChangeListener; -import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.utils.ConcurrentCacheSet; @@ -163,7 +162,7 @@ private List relayCandidates() { PeerAddress candidate = iterator.next(); // filter peers that are relayed themselves - if (candidate.isRelayed()) { + if (candidate.relaySize() > 0) { iterator.remove(); continue; } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 5d82505ff..2040e419c 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -27,7 +27,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.NeighborRPC; diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 6a3f4f6dc..565d9325a 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -116,7 +116,7 @@ public static List decomposeCompositeBuffer(ByteBuf messageBuffer, Inet ByteBuf message = messageBuffer.readBytes(size); try { - Message decodedMessage = decodeRelayedMessage(message, recipient, sender, signatureFactory); + Message decodedMessage = decodeMessage(message, recipient, sender, signatureFactory); messages.add(decodedMessage); } catch (Exception e) { LOG.error("Cannot decode buffered message. Skip it.", e); @@ -154,17 +154,18 @@ public static Message decodeMessage(ByteBuf buf, InetSocketAddress recipient, In * {@link MessageUtils#decodeMessage(Buffer, InetSocketAddress, InetSocketAddress, SignatureFactory)}, but * in addition checks that the relay peers of the decoded message are set correctly */ - public static Message decodeRelayedMessage(ByteBuf buf, InetSocketAddress recipient, InetSocketAddress sender, + /*public static Message decodeRelayedMessage(ByteBuf buf, InetSocketAddress recipient, InetSocketAddress sender, SignatureFactory signatureFactory) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { - Message decodedMessage = decodeMessage(buf, recipient, sender, signatureFactory); - boolean isRelay = decodedMessage.sender().isRelayed(); - if (isRelay && !decodedMessage.peerSocketAddresses().isEmpty()) { - PeerAddress tmpSender = decodedMessage.sender().changePeerSocketAddresses(decodedMessage.peerSocketAddresses()); + final Message decodedMessage = decodeMessage(buf, recipient, sender, signatureFactory); + final boolean isRelay = decodedMessage.sender().relaySize() > 0; + if (isRelay) { + PeerAddress tmpSender = decodedMessage.sender().withRelays(relays); + changePeerSocketAddresses(decodedMessage.peerSocketAddresses()); decodedMessage.sender(tmpSender); } return decodedMessage; - } + }*/ /** * Calculates the size of the message diff --git a/replication/src/main/java/net/tomp2p/replication/SlowReplicationFilter.java b/replication/src/main/java/net/tomp2p/replication/SlowReplicationFilter.java index f720d4944..9dc9fee46 100644 --- a/replication/src/main/java/net/tomp2p/replication/SlowReplicationFilter.java +++ b/replication/src/main/java/net/tomp2p/replication/SlowReplicationFilter.java @@ -12,7 +12,7 @@ public class SlowReplicationFilter implements ReplicationFilter { @Override public boolean rejectReplication(PeerAddress targetAddress) { - return targetAddress.isSlow(); + return targetAddress.slow(); } } diff --git a/replication/src/test/java/net/tomp2p/Utils2.java b/replication/src/test/java/net/tomp2p/Utils2.java index 3e7d04238..6d554d1e4 100644 --- a/replication/src/test/java/net/tomp2p/Utils2.java +++ b/replication/src/test/java/net/tomp2p/Utils2.java @@ -41,7 +41,6 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; -import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.replication.IndirectReplication; public class Utils2 { @@ -84,9 +83,7 @@ public static PeerAddress createAddress(String id) throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); + PeerAddress n1 = PeerAddress.create(idSender, inetSend, tcpPortSender, udpPortSender, udpPortSender + 1); return n1; } diff --git a/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java b/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java index 30d1cc58e..7608eb8f6 100644 --- a/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java +++ b/tracker/src/main/java/net/tomp2p/tracker/TrackerStorage.java @@ -276,7 +276,7 @@ public DigestInfo digest(Number160 locationKey, Number160 domainKey, Number160 c Map> trackerData = dataMap.get(new Number320(locationKey, domainKey)); if(trackerData!=null) { if(contentKey!=null) { - PeerAddress tmpAddress = new PeerAddress(contentKey); + PeerAddress tmpAddress = PeerAddress.create(contentKey); Pair pair = trackerData.get(tmpAddress); if(pair != null) { contentDigest = pair.element1().hash(); diff --git a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerStorage.java b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerStorage.java index 891f25ea4..ff956aa45 100644 --- a/tracker/src/test/java/net/tomp2p/tracker/TestTrackerStorage.java +++ b/tracker/src/test/java/net/tomp2p/tracker/TestTrackerStorage.java @@ -23,7 +23,7 @@ public class TestTrackerStorage { @Test public void testStoragePutGetVerified() throws IOException, ClassNotFoundException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, false); @@ -41,7 +41,7 @@ public void testStoragePutGetVerified() throws IOException, ClassNotFoundExcepti @Test public void testStoragePutGetUnverified() throws IOException, ClassNotFoundException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, true); @@ -58,7 +58,7 @@ public void testStoragePutGetUnverified() throws IOException, ClassNotFoundExcep @Test public void testStoragePutGetUnverifiedVerified() throws IOException, ClassNotFoundException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(Integer.MAX_VALUE, new int[] { 10 }, 1, pm, selfAddress, true); @@ -76,7 +76,7 @@ public void testStoragePutGetUnverifiedVerified() throws IOException, ClassNotFo @Test public void testStoragePutGetUnverifiedVerifiedSecurity() throws IOException, ClassNotFoundException, NoSuchAlgorithmException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(Integer.MAX_VALUE, new int[] { 10 }, 1, pm, selfAddress, true); @@ -98,7 +98,7 @@ public void testStoragePutGetUnverifiedVerifiedSecurity() throws IOException, Cl @Test public void testTrackerRemove1() throws IOException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, false); @@ -113,7 +113,7 @@ public void testTrackerRemove1() throws IOException { @Test public void testTrackerRemove2() throws IOException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, true); @@ -128,7 +128,7 @@ public void testTrackerRemove2() throws IOException { @Test public void testTrackerMaintenance1() throws IOException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, true); @@ -143,7 +143,7 @@ public void testTrackerMaintenance1() throws IOException { @Test public void testTrackerMaintenance2() throws IOException { Number160 self = Number160.ONE; - PeerAddress selfAddress = new PeerAddress(self); + PeerAddress selfAddress = PeerAddress.create(self); PeerMapConfiguration pmc = new PeerMapConfiguration(self); PeerMap pm = new PeerMap(pmc); TrackerStorage trackerStorage = new TrackerStorage(10, new int[] { 10 }, 1, pm, selfAddress, true); From c4eca870435f5fb462fb8185ca76a91caf8cf763 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 4 Nov 2015 19:29:38 +0100 Subject: [PATCH 113/135] more ipv6 and nat fixes and refactoring --- .../java/net/tomp2p/peers/PeerAddress.java | 32 ++++++++++++++---- .../net/tomp2p/peers/PeerSocketAddress.java | 4 +++ .../holep/strategy/AbstractHolePStrategy.java | 33 ++++++++++++++----- nat/src/main/java/net/tomp2p/nat/PeerNAT.java | 29 +++++++++------- .../net/tomp2p/relay/DistributedRelay.java | 18 +++++++--- .../main/java/net/tomp2p/relay/Forwarder.java | 22 ++++++++----- .../main/java/net/tomp2p/relay/RelayRPC.java | 33 ++++++++----------- .../java/net/tomp2p/relay/RelayUtils.java | 10 ++---- .../tomp2p/holep/manual/LocalNATUtils.java | 2 +- .../holep/manual/TestNATForwarding.java | 17 +++++----- .../holep/manual/TestNATHolePunching.java | 4 +-- .../net/tomp2p/holep/manual/TestNATLocal.java | 5 +-- .../net/tomp2p/holep/manual/TestNATRelay.java | 27 +++++++-------- .../tomp2p/holep/manual/TestNATStress.java | 6 ++-- .../holep/manual/TestNATTypeDetection.java | 4 +-- .../net/tomp2p/holep/manual/TestUPNP.java | 4 +-- 16 files changed, 151 insertions(+), 99 deletions(-) diff --git a/core/src/main/java/net/tomp2p/peers/PeerAddress.java b/core/src/main/java/net/tomp2p/peers/PeerAddress.java index 2339001cf..026e6ef22 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerAddress.java @@ -653,9 +653,9 @@ public static PeerAddress create(final Number160 peerId, InetAddress inet, int u - public InetSocketAddress createUDPSocket(final PeerAddress sender) { - final boolean canIPv6 = ipv6Flag && sender.ipv6Flag; - final boolean canIPv4 = ipv4Flag && sender.ipv4Flag; + public InetSocketAddress createUDPSocket(final PeerAddress other) { + final boolean canIPv6 = ipv6Flag && other.ipv6Flag; + final boolean canIPv4 = ipv4Flag && other.ipv4Flag; if((preferIPv6Addresses && canIPv6) || (!canIPv4 && canIPv6)) { if(ipv6Socket == null) { @@ -672,12 +672,32 @@ public InetSocketAddress createUDPSocket(final PeerAddress sender) { throw new RuntimeException("No matching protocal found"); } } + + public InetSocketAddress createTCPSocket(final PeerAddress other) { + final boolean canIPv6 = ipv6Flag && other.ipv6Flag; + final boolean canIPv4 = ipv4Flag && other.ipv4Flag; + if((preferIPv6Addresses && canIPv6) || + (!canIPv4 && canIPv6)) { + if(ipv6Socket == null) { + throw new RuntimeException("Flag indicates that ipv6 is present, but its not"); + } + return ipv6Socket.createTCPSocket(); + } else if(canIPv4) { + if(ipv4Socket == null) { + throw new RuntimeException("Flag indicates that ipv4 is present, but its not"); + } + return ipv4Socket.createTCPSocket(); + } + else { + throw new RuntimeException("No matching protocal found"); + } + } - public InetSocketAddress createSocket(final PeerAddress recipient, final int port) { - final boolean canIPv6 = ipv6Flag && recipient.ipv6Flag; - final boolean canIPv4 = ipv4Flag && recipient.ipv4Flag; + public InetSocketAddress createSocket(final PeerAddress other, final int port) { + final boolean canIPv6 = ipv6Flag && other.ipv6Flag; + final boolean canIPv4 = ipv4Flag && other.ipv4Flag; if((preferIPv6Addresses && canIPv6) || (!canIPv4 && canIPv6)) { if(ipv6Socket == null) { diff --git a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java index 4cf48b101..5c9d39c84 100644 --- a/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java +++ b/core/src/main/java/net/tomp2p/peers/PeerSocketAddress.java @@ -170,6 +170,10 @@ public boolean equalsWithoutPorts(final Object obj) { public int hashCode() { return Utils.hashCode(ipv4) ^ (tcpPort << 16) ^ udpPort ^ udtPort; } + + public static PeerSocket4Address create(Inet4Address inet, int udpPort, int tcpPort, int udtPort) { + return PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inet)).udpPort(udpPort).tcpPort(tcpPort).udtPort(udtPort).build(); + } } diff --git a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java index 2e386c445..91ca84bb8 100644 --- a/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java +++ b/nat/src/main/java/net/tomp2p/holep/strategy/AbstractHolePStrategy.java @@ -30,6 +30,8 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket6Address; import net.tomp2p.rpc.RPC; import net.tomp2p.rpc.RPC.Commands; import net.tomp2p.utils.Pair; @@ -553,10 +555,13 @@ protected Buffer encodePortList(final List portList) throws IOException * @return */ private Message createSendOriginalMessage(final int localPort, final int remotePort) { - final PeerAddress sender = originalMessage.sender().changePorts(-1, localPort).changeFirewalledTCP(false).changeFirewalledUDP(false) - .changeRelayed(false); - final PeerAddress recipient = originalMessage.recipient().changePorts(-1, remotePort).changeFirewalledTCP(false) - .changeFirewalledUDP(false).changeRelayed(false); + + final PeerSocket4Address ps4a1 = originalMessage.sender().ipv4Socket().withUdpPort(localPort); + final PeerAddress sender = originalMessage.sender().withUnreachable(false).withIPSocket(ps4a1).withRelaySize(0); + + final PeerSocket4Address ps4a2 = originalMessage.recipient().ipv4Socket().withUdpPort(remotePort); + final PeerAddress recipient = originalMessage.recipient().withUnreachable(false).withIPSocket(ps4a2).withRelaySize(0); + final Message sendMessage = createHolePMessage(recipient, sender, originalMessage.command(), originalMessage.type()); sendMessage.version(originalMessage.version()); sendMessage.intValue(originalMessage.messageId()); @@ -584,8 +589,15 @@ private FutureDone createInitMessage(final List channelF final FutureDone initMessageFutureDone = new FutureDone(); final PeerSocketAddress socketAddress = Utils.extractRandomRelay(originalMessage); // we need to make a copy of the original Message - final PeerAddress recipient = originalMessage.recipient().changeAddress(socketAddress.inetAddress()) - .changePorts(socketAddress.tcpPort(), socketAddress.udpPort()).changeRelayed(false); + + final PeerAddress recipient; + if(socketAddress instanceof PeerSocket4Address) { + recipient = originalMessage.recipient().withIpv4Socket((PeerSocket4Address)socketAddress).withRelaySize(0).withIpv6Socket(null); + } else { + recipient = originalMessage.recipient().withIpv6Socket((PeerSocket6Address)socketAddress).withRelaySize(0).withIpv4Socket(null); + } + + final Message initMessage = createHolePMessage(recipient, originalMessage.sender(), RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_1); initMessage.version(originalMessage.version()); initMessage.udp(true); @@ -606,8 +618,13 @@ private FutureDone createInitMessage(final List channelF private Message createDummyMessage(final int index) { final int remotePort = portMappings.get(index).element0(); final int localPort = portMappings.get(index).element1(); - final PeerAddress recipient = originalSender.changeFirewalledUDP(false).changeRelayed(false).changePorts(-1, remotePort); - final PeerAddress sender = peer.peerBean().serverPeerAddress().changePorts(-1, localPort); + + final PeerSocket4Address ps4a1 = peer.peerBean().serverPeerAddress().ipv4Socket().withUdpPort(localPort); + final PeerAddress sender = peer.peerBean().serverPeerAddress().withIPSocket(ps4a1); + + final PeerSocket4Address ps4a2 = originalMessage.recipient().ipv4Socket().withUdpPort(remotePort); + final PeerAddress recipient = originalMessage.recipient().withUnreachable(false).withIPSocket(ps4a2); + final Message dummyMessage = createHolePMessage(recipient, sender, RPC.Commands.HOLEP.getNr(), Message.Type.REQUEST_3); dummyMessage.udp(true); return dummyMessage; diff --git a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java index b852f725a..0b53c15b9 100644 --- a/nat/src/main/java/net/tomp2p/nat/PeerNAT.java +++ b/nat/src/main/java/net/tomp2p/nat/PeerNAT.java @@ -1,5 +1,6 @@ package net.tomp2p.nat; +import java.net.Inet4Address; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; @@ -24,6 +25,7 @@ import net.tomp2p.p2p.builder.BootstrapBuilder; import net.tomp2p.p2p.builder.DiscoverBuilder; import net.tomp2p.peers.PeerAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.relay.DistributedRelay; import net.tomp2p.relay.PeerMapUpdateTask; import net.tomp2p.relay.RelayRPC; @@ -101,13 +103,18 @@ public void operationComplete(FutureDiscover future) throws Exception { } if (future.isFailed() && future.isNat() && !manualPorts) { - Ports externalPorts = setupPortforwarding(future.internalAddress().getHostAddress(), peer + Ports externalPorts = setupPortforwarding(future.internalAddress().ipv4().toInetAddress().getHostAddress(), peer .connectionBean().channelServer().channelServerConfiguration().portsForwarding()); if (externalPorts != null) { final PeerAddress serverAddressOrig = peer.peerBean().serverPeerAddress(); - final PeerAddress serverAddress = serverAddressOrig.changePorts(externalPorts.tcpPort(), - externalPorts.udpPort()).changeAddress(future.externalAddress()). - changeInternalPeerSocketAddress(serverAddressOrig.peerSocketAddress()); + final PeerAddress serverAddress = serverAddressOrig + .withIpv4Socket( + PeerSocket4Address.create( + (Inet4Address)future.externalAddress().ipv4().toInetAddress(), + externalPorts.udpPort(), + externalPorts.tcpPort(), + externalPorts.udpPort() + 1)) + .withIpInternalSocket(serverAddressOrig.ipv4Socket()); // set the new address regardless wheter it will succeed // or not. @@ -123,13 +130,12 @@ public void operationComplete(FutureDiscover future) throws Exception { if (future.isSuccess()) { // UPNP or NAT-PMP was // successful, set flag - PeerAddress newServerAddress = serverAddress.changePortForwarding(true); + PeerAddress newServerAddress = serverAddress.withUnreachable(false); peer.peerBean().serverPeerAddress(newServerAddress); futureNAT.done(future.peerAddress(), future.reporter()); } else { // indicate relay - PeerAddress pa = serverAddressOrig - .changeFirewalledTCP(true).changeFirewalledUDP(true); + PeerAddress pa = serverAddressOrig.withUnreachable(true); peer.peerBean().serverPeerAddress(pa); futureNAT.failed(future); } @@ -137,8 +143,7 @@ public void operationComplete(FutureDiscover future) throws Exception { }); } else { // indicate relay - PeerAddress pa = peer.peerBean().serverPeerAddress().changeFirewalledTCP(true) - .changeFirewalledUDP(true); + PeerAddress pa = peer.peerBean().serverPeerAddress().withUnreachable(true); peer.peerBean().serverPeerAddress(pa); futureNAT.failed("could not setup NAT"); } @@ -169,7 +174,7 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { boolean success; try { - success = natUtils.mapUPNP(internalHost, peer.peerAddress().tcpPort(), peer.peerAddress().udpPort(), + success = natUtils.mapUPNP(internalHost, peer.peerAddress().ipv4Socket().tcpPort(), peer.peerAddress().ipv4Socket().udpPort(), ports.udpPort(), ports.tcpPort()); } catch (Exception e) { LOG.error("cannot map UPNP", e); @@ -181,7 +186,7 @@ public Ports setupPortforwarding(final String internalHost, Ports ports) { LOG.warn("cannot find UPNP devices"); } try { - success = natUtils.mapPMP(peer.peerAddress().tcpPort(), peer.peerAddress().udpPort(), ports.udpPort(), + success = natUtils.mapPMP(peer.peerAddress().ipv4Socket().tcpPort(), peer.peerAddress().ipv4Socket().udpPort(), ports.udpPort(), ports.tcpPort()); if (!success) { if (LOG.isWarnEnabled()) { @@ -322,7 +327,7 @@ private Message createSetupMessage(final PeerAddress relayPeerAddress, Message setUpMessage = new Message(); setUpMessage.version(peer.connectionBean().p2pId()); setUpMessage.sender(peer.peerAddress()); - setUpMessage.recipient(relayPeerAddress.changePeerId(unreachablePeerAddress.peerId())); + setUpMessage.recipient(relayPeerAddress.withPeerId(unreachablePeerAddress.peerId())); setUpMessage.command(RPC.Commands.RCON.getNr()); setUpMessage.type(Type.REQUEST_1); // setUpMessage.keepAlive(true); diff --git a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java index b01218a9e..dba7e4b45 100644 --- a/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java +++ b/nat/src/main/java/net/tomp2p/relay/DistributedRelay.java @@ -25,6 +25,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMapChangeListener; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.utils.ConcurrentCacheSet; @@ -300,17 +301,24 @@ public void operationComplete(final FutureDone futureClose) */ private void updatePeerAddress() { final boolean hasRelays; - final Collection socketAddresses; + final Collection socketAddresses; synchronized (activeClients) { // add relay addresses to peer address hasRelays = !activeClients.isEmpty(); - socketAddresses = new ArrayList(activeClients.size()); + socketAddresses = new ArrayList(activeClients.size()); //we can have more than the max relay count in our active client list. int max = 5; int i = 0; for (PeerAddress relay : activeClients.keySet()) { - socketAddresses.add(new PeerSocketAddress2(relay.inetAddress(), relay.tcpPort(), relay.udpPort())); + + if(relay.ipv4Flag()) { + socketAddresses.add(relay.ipv4Socket()); + } + if(relay.ipv6Flag()) { + socketAddresses.add(relay.ipv6Socket()); + } + if(i++ >= max) { break; } @@ -318,8 +326,8 @@ private void updatePeerAddress() { } // update firewalled and isRelayed flags - PeerAddress newAddress = peer.peerAddress().changeFirewalledTCP(!hasRelays).changeFirewalledUDP(!hasRelays) - .changeRelayed(hasRelays).changePeerSocketAddresses(socketAddresses); + PeerAddress newAddress = peer.peerAddress().withRelays(socketAddresses); + peer.peerBean().serverPeerAddress(newAddress); LOG.debug("Updated peer address {}, isrelay = {}", newAddress, hasRelays); } diff --git a/nat/src/main/java/net/tomp2p/relay/Forwarder.java b/nat/src/main/java/net/tomp2p/relay/Forwarder.java index 2040e419c..381725ba4 100644 --- a/nat/src/main/java/net/tomp2p/relay/Forwarder.java +++ b/nat/src/main/java/net/tomp2p/relay/Forwarder.java @@ -87,9 +87,12 @@ public FutureDone forwardToUnreachable(final Message message) { envelope.keepAlive(true); // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress2(message.sender().inetAddress(), 0, 0)); - envelope.peerSocketAddresses(peerSocketAddresses); + if(envelope.sender().ipv4Flag()) { + envelope.peerSocket4Address(envelope.sender().ipv4Socket()); + } + if(envelope.sender().ipv6Flag()) { + envelope.peerSocket6Address(envelope.sender().ipv6Socket()); + } // holds the message that will be returned to he requester final FutureDone futureDone = new FutureDone(); @@ -101,11 +104,11 @@ public void operationComplete(FutureResponse future) throws Exception { if (future.isSuccess()) { InetSocketAddress senderSocket = message.recipientSocket(); if (senderSocket == null) { - senderSocket = unreachablePeerConnection.remotePeer().createSocketTCP(); + senderSocket = unreachablePeerConnection.remotePeer().ipv4Socket().createTCPSocket(); } InetSocketAddress recipientSocket = message.senderSocket(); if (recipientSocket == null) { - recipientSocket = message.sender().createSocketTCP(); + recipientSocket = message.sender().ipv4Socket().createTCPSocket(); } Buffer buffer = future.responseMessage().buffer(0); @@ -294,9 +297,12 @@ private void forwardMessages(List buffer2) { envelope.buffer(new Buffer(bb)); // this will be read RelayRPC.handlePiggyBackMessage - Collection peerSocketAddresses = new ArrayList(1); - peerSocketAddresses.add(new PeerSocketAddress2(envelope.sender().inetAddress(), 0, 0)); - envelope.peerSocketAddresses(peerSocketAddresses); + if(envelope.sender().ipv4Flag()) { + envelope.peerSocket4Address(envelope.sender().ipv4Socket()); + } + if(envelope.sender().ipv6Flag()) { + envelope.peerSocket6Address(envelope.sender().ipv6Socket()); + } // Forward a message through the open peer connection to the unreachable peer. RelayUtils.send(unreachablePeerConnection, peerBean(), connectionBean(), envelope); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index 2b2183e0d..a24efcbd8 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -6,7 +6,6 @@ import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -31,7 +30,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerStatistic; import net.tomp2p.rpc.DispatchHandler; import net.tomp2p.rpc.RPC; @@ -239,17 +238,16 @@ private Dispatcher dispatcher() { private void handleSetup(Message message, final PeerConnection unreachablePeerConnectionOrig, final Responder responder) { final Number160 unreachablePeerId = unreachablePeerConnectionOrig.remotePeer().peerId(); //add myself as relay - Collection psa = unreachablePeerConnectionOrig.remotePeer().peerSocketAddresses(); - Collection psa2 = new ArrayList(psa); - - psa2.add(peer().peerAddress().peerSocketAddress()); + Collection psa = unreachablePeerConnectionOrig.remotePeer().relays(); + psa.addAll(peer().peerAddress().relays()); + final PeerConnection unreachablePeerConnectionCopy = unreachablePeerConnectionOrig.changeRemotePeer( - unreachablePeerConnectionOrig.remotePeer().changeRelayed(true).changeFirewalledTCP(false).changeFirewalledUDP(false).changePeerSocketAddresses(psa2)); + unreachablePeerConnectionOrig.remotePeer().withRelays(psa)); //now we can add this peer to the map, as we have now set the flag //its TCP, we have a connection to this peer, so mark it as first hand peerBean().notifyPeerFound(unreachablePeerConnectionCopy.remotePeer(), null, unreachablePeerConnectionCopy, null); - final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().isSlow(), bufferTimeoutSeconds, bufferSize); + final Forwarder forwarder = new Forwarder(peer, unreachablePeerConnectionCopy, message.sender().slow(), bufferTimeoutSeconds, bufferSize); for (Commands command : RPC.Commands.values()) { if (command == RPC.Commands.RCON) { // We must register the rconRPC for every unreachable peer that @@ -283,10 +281,10 @@ private void handlePiggyBackedMessage(Message message, final Responder responder // TODO: check if we have right setup // this contains the real sender - Collection peerSocketAddresses = message.peerSocketAddresses(); + PeerSocketAddress peerSocketAddress = message.peerSocket4Address(0); final InetSocketAddress sender; - if (!peerSocketAddresses.isEmpty()) { - sender = PeerSocketAddress2.createSocketTCP(peerSocketAddresses.iterator().next()); + if (peerSocketAddress != null) { + sender = peerSocketAddress.createTCPSocket(); } else { sender = new InetSocketAddress(0); } @@ -306,9 +304,6 @@ public FutureDone response(Message responseMessage) { final FutureDone futureDone = new FutureDone(); LOG.debug("Send reply message to relay peer: {}", responseMessage); try { - if (responseMessage.sender().isRelayed() && !responseMessage.sender().peerSocketAddresses().isEmpty()) { - responseMessage.peerSocketAddresses(responseMessage.sender().peerSocketAddresses()); - } envelope.buffer(RelayUtils.encodeMessage(responseMessage, signatureFactory())); } catch (Exception e) { LOG.error("Cannot piggyback the response", e); @@ -375,18 +370,18 @@ public void handleBuffer(final Message message) throws InvalidKeyException, NoSu return; } List buffered = RelayUtils.decomposeCompositeBuffer( - message.buffer(0).buffer(), message.recipient().createSocketTCP(), - message.sender().createSocketTCP(), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); + message.buffer(0).buffer(), message.recipient().createTCPSocket(message.sender()), + message.sender().createTCPSocket(message.recipient()), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); LOG.debug("got {} messages", buffered.size()); for(Message msg:buffered) { DispatchHandler dh = connectionBean().dispatcher().associatedHandler(msg); //TODO: add a custom responder and respond to the address found in the message - dh.forwardMessage(msg, null, createResponder(peer, msg.sender().peerSocketAddress())); + dh.forwardMessage(msg, null, createResponder(peer, msg.sender().ipv4Socket())); } } - private static Responder createResponder(final Peer peer, final PeerSocketAddress2 sender) { + private static Responder createResponder(final Peer peer, final PeerSocketAddress sender) { return new Responder() { @Override @@ -395,7 +390,7 @@ public void responseFireAndForget() {} @Override public FutureDone response(final Message responseMessage) { - responseMessage.recipient(responseMessage.recipient().changeAddress(sender.inetAddress()).changePorts(sender.tcpPort(), sender.udpPort())); + responseMessage.recipient(responseMessage.recipient().withIPSocket(sender)); LOG.debug("send late reply {}", responseMessage); final FutureResponse fr = RelayUtils.connectAndSend(peer, responseMessage); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 565d9325a..1c5c6bdc4 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -154,18 +154,12 @@ public static Message decodeMessage(ByteBuf buf, InetSocketAddress recipient, In * {@link MessageUtils#decodeMessage(Buffer, InetSocketAddress, InetSocketAddress, SignatureFactory)}, but * in addition checks that the relay peers of the decoded message are set correctly */ - /*public static Message decodeRelayedMessage(ByteBuf buf, InetSocketAddress recipient, InetSocketAddress sender, + public static Message decodeRelayedMessage(ByteBuf buf, InetSocketAddress recipient, InetSocketAddress sender, SignatureFactory signatureFactory) throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, IOException { final Message decodedMessage = decodeMessage(buf, recipient, sender, signatureFactory); - final boolean isRelay = decodedMessage.sender().relaySize() > 0; - if (isRelay) { - PeerAddress tmpSender = decodedMessage.sender().withRelays(relays); - changePeerSocketAddresses(decodedMessage.peerSocketAddresses()); - decodedMessage.sender(tmpSender); - } return decodedMessage; - }*/ + } /** * Calculates the size of the message diff --git a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java index fb2467140..fe129ec0f 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/LocalNATUtils.java @@ -272,7 +272,7 @@ public void run() { } public static PeerAddress peerAddress(String ip, int port, int peerId) throws UnknownHostException { - return new PeerAddress(Number160.createHash(peerId), ip, port, port); + return PeerAddress.create(Number160.createHash(peerId), ip, port, port, port); } public static Peer init(String ip, int port, int peerId) diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java index 641295a59..778d0952b 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATForwarding.java @@ -16,7 +16,8 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; //travis-ci cannot test this, the kernel does not support all the required features: //Perhaps iptables or your kernel needs to be upgraded @@ -52,7 +53,7 @@ public void testForwardTwoPeers() throws Exception { try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); @@ -79,7 +80,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + PeerAddress peer2 = PeerAddress.create(Number160.createHash(1), "172.20.1.1", 4000, 4000, 4001); FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); Assert.assertEquals("peer2", fdir.object()); return "done"; @@ -113,7 +114,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - PeerAddress peer2 = new PeerAddress(Number160.createHash(0), "172.20.0.1", 4000, 4000); + PeerAddress peer2 = PeerAddress.create(Number160.createHash(0), "172.20.0.1", 4000, 4000, 4001); FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); Assert.assertEquals("peer1", fdir.object()); return "done"; @@ -151,7 +152,7 @@ public void testForwardTwoPlusOne() throws Exception { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); final Peer regularPeer = LocalNATUtils.createRealNode(Number160.createHash(77), INF, 5003); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); CommandSync sync = new CommandSync(2); @@ -162,7 +163,7 @@ public void testForwardTwoPlusOne() throws Exception { public void run() { try { Thread.sleep(5000); - PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + PeerAddress peer2 = PeerAddress.create(Number160.createHash(1), "172.20.1.1", 4000, 4000, 4001); FutureDirect fdir = regularPeer.sendDirect(peer2).object("test").start().awaitUninterruptibly(); Assert.assertEquals("peer2", fdir.object()); } catch (Exception e) { @@ -197,7 +198,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - PeerAddress peer2 = new PeerAddress(Number160.createHash(1), "172.20.1.1", 4000, 4000); + PeerAddress peer2 = PeerAddress.create(Number160.createHash(1), "172.20.1.1", 4000, 4000, 4001); FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); Assert.assertEquals("peer2", fdir.object()); return "done"; @@ -231,7 +232,7 @@ public Serializable execute() throws Exception { @Override public Serializable execute() throws Exception { final Peer peer1 = (Peer) get("p1"); - PeerAddress peer2 = new PeerAddress(Number160.createHash(0), "172.20.0.1", 4000, 4000); + PeerAddress peer2 = PeerAddress.create(Number160.createHash(0), "172.20.0.1", 4000, 4000, 4001); FutureDirect fdir = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); Assert.assertEquals("peer1", fdir.object()); return "done"; diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java index e30ea09ec..19d43bd10 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATHolePunching.java @@ -63,7 +63,7 @@ public void after() throws IOException, InterruptedException { private static Serializable discover(final String address, Peer peer) throws UnknownHostException { - PeerAddress relayP = new PeerAddress(relayPeerId, address, 5002, 5002); + PeerAddress relayP = PeerAddress.create(relayPeerId, address, 5002, 5002, 5003); FutureDone type = NATTypeDetection.checkNATType(peer, relayP) .awaitUninterruptibly(); return type.isSuccess() ? type.object().name() : type.failedReason(); @@ -77,7 +77,7 @@ public void testDetection() throws Exception { RemotePeer unr2 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); + InetAddress relayAddress = relayPeer.peerAddress().ipv4Socket().ipv4().toInetAddress(); final String address = relayAddress.getHostAddress(); CommandSync sync = new CommandSync(2); unr1 = LocalNATUtils.executePeer(0, sync, diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index 22832896a..c91886906 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -13,7 +13,8 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import org.junit.After; import org.junit.Assert; @@ -68,7 +69,7 @@ public void testLocalSend() throws Exception { RemotePeer unr1 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index d06eb378e..dd6f236fc 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -23,6 +23,7 @@ import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.relay.Forwarder; import net.tomp2p.relay.RelayCallback; import net.tomp2p.rpc.ObjectDataReply; @@ -70,8 +71,8 @@ public void testRelayFailover1() throws Exception { try { relayPeer1 = createRelay(relayPeerId1, 5002); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); - final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress1 = relayPeer1.peerAddress().ipv4Socket(); + final PeerSocket4Address relayAddress2 = relayPeer2.peerAddress().ipv4Socket(); final Peer relayPeer1Copy = relayPeer1; CommandSync sync = new CommandSync(1); @@ -161,9 +162,9 @@ public void testRelayFailover2() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress1 = relayPeer1.peerAddress().ipv4Socket(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress2 = relayPeer2.peerAddress().ipv4Socket(); final Peer relayPeer1Copy = relayPeer1; final Peer relayPeer2Copy = relayPeer2; @@ -257,15 +258,15 @@ public void testFullRelay() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress1 = relayPeer1.peerAddress().ipv4Socket(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress2 = relayPeer2.peerAddress().ipv4Socket(); relayPeer3 = createRelay(relayPeerId3, 5004); - final PeerSocketAddress2 relayAddress3 = relayPeer3.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress3 = relayPeer3.peerAddress().ipv4Socket(); relayPeer4 = createRelay(relayPeerId4, 5005); - final PeerSocketAddress2 relayAddress4 = relayPeer4.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress4 = relayPeer4.peerAddress().ipv4Socket(); relayPeer5 = createRelay(relayPeerId5, 5006); - final PeerSocketAddress2 relayAddress5 = relayPeer5.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress5 = relayPeer5.peerAddress().ipv4Socket(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -330,9 +331,9 @@ public void testLateRelay() throws Exception { RemotePeer unr1 = null; try { relayPeer1 = createRelay(relayPeerId1, 5002); - final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress1 = relayPeer1.peerAddress().ipv4Socket(); relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress2 = relayPeer2.peerAddress().ipv4Socket(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -458,7 +459,7 @@ public void testRealRelayDifferentNAT() throws Exception { RemotePeer unr2 = null; try { relayPeer = createRelay(relayPeerId1, 5002); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); CommandSync sync = new CommandSync(2); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { @@ -611,7 +612,7 @@ public void testRealRelaySameNAT() throws Exception { RemotePeer unr1 = null; try { relayPeer = createRelay(relayPeerId1, 5002); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); CommandSync sync = new CommandSync(1); unr1 = LocalNATUtils.executePeer(0, sync, new Command() { diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java index 45680911f..76b3fa48a 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATStress.java @@ -26,7 +26,7 @@ import net.tomp2p.p2p.RequestP2PConfiguration; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.relay.RelayCallback; import net.tomp2p.storage.Data; @@ -94,8 +94,8 @@ public void testStress() throws Exception { relayDHT1 = new PeerBuilderDHT(relayPeer1).start(); final Peer relayPeer11 = relayPeer1; relayPeer2 = createRelay(relayPeerId2, 5003); - final PeerSocketAddress2 relayAddress1 = relayPeer1.peerAddress().peerSocketAddress(); - final PeerSocketAddress2 relayAddress2 = relayPeer2.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress1 = relayPeer1.peerAddress().ipv4Socket(); + final PeerSocket4Address relayAddress2 = relayPeer2.peerAddress().ipv4Socket(); System.out.println("relay 1:"+relayPeer1.peerAddress()); System.out.println("relay 2:"+relayPeer2.peerAddress()); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java index e1fdd8941..7078c8713 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATTypeDetection.java @@ -63,7 +63,7 @@ public void after() throws IOException, InterruptedException { private static Serializable discover(final String address, Peer peer) throws UnknownHostException { - PeerAddress relayP = new PeerAddress(relayPeerId, address, 5002, 5002); + PeerAddress relayP = PeerAddress.create(relayPeerId, address, 5002, 5002, 5003); FutureDone type = NATTypeDetection.checkNATType(peer, relayP) .awaitUninterruptibly(); return type.isSuccess() ? type.object().name() : type.failedReason(); @@ -77,7 +77,7 @@ public void testDetection() throws Exception { RemotePeer unr2 = null; try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); - InetAddress relayAddress = relayPeer.peerAddress().inetAddress(); + InetAddress relayAddress = relayPeer.peerAddress().ipv4Socket().ipv4().toInetAddress(); final String address = relayAddress.getHostAddress(); CommandSync sync = new CommandSync(2); unr1 = LocalNATUtils.executePeer(0, sync, diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java index 7feaceb50..595138332 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestUPNP.java @@ -21,7 +21,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.storage.Data; //travis-ci cannot test this, the kernel does not support all the required features: @@ -58,7 +58,7 @@ public void testUPNP() throws Exception { try { relayPeer = LocalNATUtils.createRealNode(relayPeerId, INF, 5002); pd = new PeerBuilderDHT(relayPeer).start(); - final PeerSocketAddress2 relayAddress = relayPeer.peerAddress().peerSocketAddress(); + final PeerSocket4Address relayAddress = relayPeer.peerAddress().ipv4Socket(); final PeerAddress relay = relayPeer.peerAddress(); System.out.println("relay peer at: "+relay); From d294f2dc2858e4cd32f30972b8b299a89f526bef Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 17 Nov 2015 18:12:31 +0100 Subject: [PATCH 114/135] fix composite buffer, added recursion --- .../tomp2p/message/MessageHeaderCodec.java | 19 +++++++---- .../storage/AlternativeCompositeByteBuf.java | 33 ++++++++++++------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java index 8780b55e7..52c38b644 100644 --- a/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java +++ b/core/src/main/java/net/tomp2p/message/MessageHeaderCodec.java @@ -112,7 +112,12 @@ public static boolean decodeHeader(final ByteBuf buffer, final InetSocketAddress final int command = buffer.readUnsignedByte(); message.command((byte) command); final Number160 recipientID = Number160.decode(buffer); - message.recipient(PeerAddress.builder().peerId(recipientID).build()); + + //we only get the id for the recipient, the rest we already know + final PeerAddress recipient = PeerAddress.builder().peerId(recipientID).build(); + message.recipient(recipient); + + final int contentTypes = buffer.readInt(); message.hasContent(contentTypes != 0); message.contentTypes(decodeContentTypes(contentTypes, message)); @@ -126,15 +131,17 @@ public static boolean decodeHeader(final ByteBuf buffer, final InetSocketAddress if(3 + buffer.readableBytes() < peerAddressSize) { return false; } - PeerAddress peerAddress = PeerAddress.decode(header, buffer); + + final PeerAddress sender = PeerAddress.decode(header, buffer); if(senderSocket.getAddress() instanceof Inet4Address) { - PeerSocket4Address psa4 = peerAddress.ipv4Socket().withIpv4(IPv4.fromInet4Address(senderSocket.getAddress())); - message.sender(peerAddress.withIpv4Socket(psa4)); + PeerSocket4Address psa4 = sender.ipv4Socket().withIpv4(IPv4.fromInet4Address(senderSocket.getAddress())); + message.sender(sender.withIpv4Socket(psa4)); } else { - PeerSocket6Address psa6 = peerAddress.ipv6Socket().withIpv6(IPv6.fromInet6Address(senderSocket.getAddress())); - message.sender(peerAddress.withIpv6Socket(psa6)); + PeerSocket6Address psa6 = sender.ipv6Socket().withIpv6(IPv6.fromInet6Address(senderSocket.getAddress())); + message.sender(sender.withIpv6Socket(psa6)); } + //keep the original sockets message.senderSocket(senderSocket); message.recipientSocket(recipientSocket); diff --git a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java index 71fbb670d..78eae5b7c 100644 --- a/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java +++ b/core/src/main/java/net/tomp2p/storage/AlternativeCompositeByteBuf.java @@ -101,8 +101,13 @@ private final class Component { this.buf = buf; } - int endOffset() { + int readable() { return offset + buf.readableBytes(); + + } + + int capacity() { + return offset + buf.capacity(); } } @@ -327,7 +332,7 @@ private void addComponentElement(final boolean fillBuffer, final ByteBuf b) { c.offset = prev.offset + prev.buf.capacity(); } else { // the buffer may not get filled - c.offset = prev.endOffset(); + c.offset = prev.readable(); } } writerIndex0(writerIndex() + c.buf.writerIndex()); @@ -524,11 +529,11 @@ public AlternativeCompositeByteBuf discardSomeReadBytes() { c.offset = c.offset - offsetAdjustment; } - if(readerIndex >= c.endOffset()) { + if(readerIndex >= c.readable()) { c.buf.release(); iterator.remove(); isOffsetAdjustment = true; - int adjust = c.endOffset() - c.offset; + int adjust = c.readable() - c.offset; setIndex0(readerIndex - adjust, writerIndex - adjust); offsetAdjustment += adjust; } else { @@ -705,7 +710,7 @@ public short getUnsignedByte(int index) { @Override public short getShort(int index) { Component c = findComponent(index); - if (index + 2 <= c.endOffset()) { + if (index + 2 <= c.readable()) { return c.buf.getShort(index - c.offset); } else if (order() == ByteOrder.BIG_ENDIAN) { return (short) ((getByte(index) & 0xff) << 8 | getByte(index + 1) & 0xff); @@ -731,7 +736,7 @@ public int getMedium(int index) { @Override public int getUnsignedMedium(int index) { Component c = findComponent(index); - if (index + 3 <= c.endOffset()) { + if (index + 3 <= c.readable()) { return c.buf.getUnsignedMedium(index - c.offset); } else if (order() == ByteOrder.BIG_ENDIAN) { return (getShort(index) & 0xffff) << 8 | getByte(index + 2) & 0xff; @@ -743,7 +748,7 @@ public int getUnsignedMedium(int index) { @Override public int getInt(int index) { Component c = findComponent(index); - if (index + 4 <= c.endOffset()) { + if (index + 4 <= c.readable()) { return c.buf.getInt(index - c.offset); } else if (order() == ByteOrder.BIG_ENDIAN) { return (getShort(index) & 0xffff) << 16 | getShort(index + 2) @@ -762,7 +767,7 @@ public long getUnsignedInt(int index) { @Override public long getLong(int index) { Component c = findComponent(index); - if (index + 8 <= c.endOffset()) { + if (index + 8 <= c.readable()) { return c.buf.getLong(index - c.offset); } else if (order() == ByteOrder.BIG_ENDIAN) { return (getInt(index) & 0xffffffffL) << 32 | getInt(index + 4) @@ -958,7 +963,7 @@ public AlternativeCompositeByteBuf setByte(int index, int value) { @Override public AlternativeCompositeByteBuf setShort(int index, int value) { Component c = findComponent(index); - if (index + 2 <= c.endOffset()) { + if (index + 2 <= c.capacity()) { c.buf.setShort(index - c.offset, value); } else if (order() == ByteOrder.BIG_ENDIAN) { setByte(index, (byte) (value >>> 8)); @@ -973,7 +978,7 @@ public AlternativeCompositeByteBuf setShort(int index, int value) { @Override public AlternativeCompositeByteBuf setMedium(int index, int value) { Component c = findComponent(index); - if (index + 3 <= c.endOffset()) { + if (index + 3 <= c.capacity()) { c.buf.setMedium(index - c.offset, value); } else if (order() == ByteOrder.BIG_ENDIAN) { setShort(index, (short) (value >> 8)); @@ -988,7 +993,7 @@ public AlternativeCompositeByteBuf setMedium(int index, int value) { @Override public AlternativeCompositeByteBuf setInt(int index, int value) { Component c = findComponent(index); - if (index + 4 <= c.endOffset()) { + if (index + 4 <= c.capacity()) { c.buf.setInt(index - c.offset, value); } else if (order() == ByteOrder.BIG_ENDIAN) { setShort(index, (short) (value >>> 16)); @@ -1003,7 +1008,7 @@ public AlternativeCompositeByteBuf setInt(int index, int value) { @Override public AlternativeCompositeByteBuf setLong(int index, long value) { Component c = findComponent(index); - if (index + 8 <= c.endOffset()) { + if (index + 8 <= c.capacity()) { c.buf.setLong(index - c.offset, value); } else if (order() == ByteOrder.BIG_ENDIAN) { setInt(index, (int) (value >>> 32)); @@ -1509,6 +1514,10 @@ private void increaseComponentWriterIndex(final int increase) { int index = findIndex(writerIndex); while (maxIncrease < increase) { Component c = components.get(index); + //recursively adjust the index + if(c.buf.unwrap() instanceof AlternativeCompositeByteBuf) { + ((AlternativeCompositeByteBuf)c.buf.unwrap()).increaseComponentWriterIndex(currentIncrease); + } int writable = c.buf.writableBytes(); writable = Math.min(writable, currentIncrease); c.buf.writerIndex(c.buf.writerIndex() + writable); From 6056e8050c509f2a53965d2bc41b6f34f207f4e8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 17 Nov 2015 18:51:53 +0100 Subject: [PATCH 115/135] fixed errors and testcases, lombok requires an encoding parameter --- .../main/java/net/tomp2p/relay/RelayRPC.java | 4 ++-- .../java/net/tomp2p/relay/RelayUtils.java | 1 + .../net/tomp2p/holep/manual/TestNATLocal.java | 9 ++++---- .../net/tomp2p/holep/manual/TestNATRelay.java | 12 ++++------ .../test/java/net/tomp2p/relay/TestRcon.java | 6 ++--- .../java/net/tomp2p/relay/TestRelayUtils.java | 23 ++++++++++--------- .../test/java/net/tomp2p/relay/TestSlow.java | 11 +++------ .../test/java/net/tomp2p/relay/UtilsNAT.java | 16 ++++--------- pom.xml | 3 +++ 9 files changed, 38 insertions(+), 47 deletions(-) diff --git a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java index a24efcbd8..2c6781baf 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayRPC.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayRPC.java @@ -370,8 +370,8 @@ public void handleBuffer(final Message message) throws InvalidKeyException, NoSu return; } List buffered = RelayUtils.decomposeCompositeBuffer( - message.buffer(0).buffer(), message.recipient().createTCPSocket(message.sender()), - message.sender().createTCPSocket(message.recipient()), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); + message.buffer(0).buffer(), message.recipientSocket(), + message.senderSocket(), peer.connectionBean().sender().channelClientConfiguration().signatureFactory()); LOG.debug("got {} messages", buffered.size()); for(Message msg:buffered) { DispatchHandler dh = connectionBean().dispatcher().associatedHandler(msg); diff --git a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java index 1c5c6bdc4..2317188f3 100644 --- a/nat/src/main/java/net/tomp2p/relay/RelayUtils.java +++ b/nat/src/main/java/net/tomp2p/relay/RelayUtils.java @@ -133,6 +133,7 @@ public static Buffer encodeMessage(Message message, SignatureFactory signatureFa Encoder e = new Encoder(signatureFactory); AlternativeCompositeByteBuf buf = AlternativeCompositeByteBuf.compBuffer(AlternativeCompositeByteBuf.UNPOOLED_HEAP); e.write(buf, message, message.receivedSignature()); + System.err.println("got: "+buf); return new Buffer(buf); } diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java index c91886906..8775684e9 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATLocal.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.io.Serializable; +import java.net.Inet4Address; import java.net.InetAddress; import java.util.Random; @@ -95,9 +96,9 @@ public Serializable execute() throws Exception { if(fn1.isSuccess() && fn2.isSuccess()) { // now peer1 and peer2 know each other locally. PeerAddress punr2 = peer2.peerAddress(); - InetAddress internal = InetAddress.getByName("0.0.0.3"); - punr2 = punr2.changeInternalPeerSocketAddress(new PeerSocketAddress2(internal, 5001, 5001)); - punr2 = punr2.changePortForwarding(true); + InetAddress internal = Inet4Address.getByName("0.0.0.3"); + punr2 = punr2.withIpInternalSocket((PeerSocket4Address)PeerSocketAddress.create(internal, 5001, 5001, 5002)); + //TODO: mark reachable FuturePing fp1 = peer1.ping().peerAddress(punr2).start().awaitUninterruptibly(); sb.append(fp1.isSuccess()); System.out.println(fp1.failedReason() + " /" + fp1.remotePeer()); @@ -106,7 +107,7 @@ public Serializable execute() throws Exception { System.out.println(fp1.failedReason() + " /" + fp2.remotePeer()); sb.append(fp2.isSuccess()); System.out.println(peer1.peerBean().peerMap().getPeerStatistic(punr2).peerAddress()); - sb.append(peer1.peerBean().peerMap().getPeerStatistic(punr2).peerAddress().inetAddress()); + sb.append(peer1.peerBean().peerMap().getPeerStatistic(punr2).peerAddress()); } else { System.err.println("failed: "+ fn1.failedReason() + fn2.failedReason()); return fn1.failedReason() + fn2.failedReason(); diff --git a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java index dd6f236fc..f2d23c2b1 100644 --- a/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java +++ b/nat/src/test/java/net/tomp2p/holep/manual/TestNATRelay.java @@ -22,7 +22,7 @@ import net.tomp2p.p2p.Peer; import net.tomp2p.peers.Number160; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; import net.tomp2p.peers.PeerSocketAddress.PeerSocket4Address; import net.tomp2p.relay.Forwarder; import net.tomp2p.relay.RelayCallback; @@ -479,10 +479,9 @@ public Serializable execute() throws Exception { Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.1.2", 5000, 1); - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(relayAddress); - peer2 = peer2.changePeerSocketAddresses(psa); - peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); + peer2 = peer2.withRelays(psa); FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); @@ -520,10 +519,9 @@ public Serializable execute() throws Exception { Thread.sleep(500); PeerAddress peer2 = LocalNATUtils.peerAddress("10.0.0.2", 5000, 0); - Collection psa = new ArrayList(); + Collection psa = new ArrayList(); psa.add(relayAddress); - peer2 = peer2.changePeerSocketAddresses(psa); - peer2 = peer2.changeFirewalledTCP(true).changeFirewalledUDP(true).changeRelayed(true); + peer2 = peer2.withRelays(psa); FutureDirect fdir1 = peer1.sendDirect(peer2).object("test").start().awaitUninterruptibly(); System.out.println(fdir1.failedReason()); Assert.assertTrue(fdir1.isSuccess()); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRcon.java b/nat/src/test/java/net/tomp2p/relay/TestRcon.java index a74812ea8..2850bf71b 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRcon.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRcon.java @@ -55,7 +55,7 @@ public void setupRelay() throws Exception { // Test setting up relay peers unreachable = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORTS + 1).start(); PeerAddress pa = unreachable.peerBean().serverPeerAddress(); - pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true); + pa = pa.withUnreachable(true); unreachable.peerBean().serverPeerAddress(pa); // find neighbors @@ -69,9 +69,7 @@ public void setupRelay() throws Exception { Thread.sleep(5000); // Check if flags are set correctly - Assert.assertTrue(unreachable.peerAddress().isRelayed()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledTCP()); - Assert.assertFalse(unreachable.peerAddress().isFirewalledUDP()); + Assert.assertTrue(unreachable.peerAddress().relays().size() > 0); System.err.println("master = " + master.peerAddress()); System.err.println("reachable = " + reachable.peerAddress()); diff --git a/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java b/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java index 7624c65b4..481db1025 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java +++ b/nat/src/test/java/net/tomp2p/relay/TestRelayUtils.java @@ -18,7 +18,7 @@ import net.tomp2p.message.Buffer; import net.tomp2p.message.Message; import net.tomp2p.peers.PeerAddress; -import net.tomp2p.peers.PeerSocketAddress2; +import net.tomp2p.peers.PeerSocketAddress; import org.junit.Assert; import org.junit.Test; @@ -51,23 +51,24 @@ public void testEncodeDecodeRelayedMessage() throws InvalidKeyException, Signatu InvalidKeySpecException { Message message = UtilsNAT.createRandomMessage(); - List relays = new ArrayList(); - relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8000, 9000)); - relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8001, 9001)); - relays.add(new PeerSocketAddress2(InetAddress.getLocalHost(), 8002, 9002)); + List relays = new ArrayList(); + relays.add(PeerSocketAddress.create(InetAddress.getLocalHost(), 8000, 9000, 9001)); + relays.add(PeerSocketAddress.create(InetAddress.getLocalHost(), 8001, 9001, 9002)); + relays.add(PeerSocketAddress.create(InetAddress.getLocalHost(), 8002, 9002, 9003)); - PeerAddress sender = UtilsNAT.createRandomAddress().changeRelayed(true).changePeerSocketAddresses(relays) - .changeFirewalledTCP(true).changeFirewalledUDP(true); + PeerAddress sender = UtilsNAT.createRandomAddress().withRelays(relays);; + PeerAddress receiver = UtilsNAT.createRandomAddress(); + message.sender(sender); - message.senderSocket(sender.createSocketTCP()); + message.senderSocket(sender.createTCPSocket(receiver)); + - PeerAddress receiver = UtilsNAT.createRandomAddress(); message.recipient(receiver); - message.recipientSocket(receiver.createSocketTCP()); + message.recipientSocket(receiver.createTCPSocket(sender)); Buffer encoded = RelayUtils.encodeMessage(message, signature); Message decoded = RelayUtils.decodeMessage(encoded.buffer(), message.recipientSocket(), message.senderSocket(), signature); - Assert.assertEquals(message.peerSocketAddresses().size(), decoded.peerSocketAddresses().size()); + Assert.assertEquals(message.sender().relays(), decoded.sender().relays()); } @Test diff --git a/nat/src/test/java/net/tomp2p/relay/TestSlow.java b/nat/src/test/java/net/tomp2p/relay/TestSlow.java index 35f140c21..1c020c1ed 100644 --- a/nat/src/test/java/net/tomp2p/relay/TestSlow.java +++ b/nat/src/test/java/net/tomp2p/relay/TestSlow.java @@ -9,12 +9,9 @@ import org.junit.Before; import org.junit.Test; -import net.tomp2p.connection.PeerConnection; import net.tomp2p.futures.BaseFuture; -import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; -import net.tomp2p.futures.FutureDone; import net.tomp2p.nat.PeerBuilderNAT; import net.tomp2p.nat.PeerNAT; import net.tomp2p.p2p.Peer; @@ -50,7 +47,7 @@ public void setupRelay() throws Exception { // Test setting up relay peers slow = new PeerBuilder(Number160.createHash(RND.nextInt())).ports(PORTS + 1).start(); PeerAddress pa = slow.peerBean().serverPeerAddress(); - pa = pa.changeFirewalledTCP(true).changeFirewalledUDP(true).changeSlow(true); + pa = pa.withUnreachable(true).withSlow(true); slow.peerBean().serverPeerAddress(pa); // find neighbors @@ -64,10 +61,8 @@ public void setupRelay() throws Exception { Thread.sleep(5000); // Check if flags are set correctly - Assert.assertTrue(slow.peerAddress().isRelayed()); - Assert.assertFalse(slow.peerAddress().isFirewalledTCP()); - Assert.assertFalse(slow.peerAddress().isFirewalledUDP()); - Assert.assertTrue(slow.peerAddress().isSlow()); + Assert.assertTrue(slow.peerAddress().relays().size() > 0); + Assert.assertTrue(slow.peerAddress().slow()); System.err.println("master = " + master.peerAddress()); System.err.println("reachable = " + reachable.peerAddress()); diff --git a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java index 0b99ed002..81e440ade 100644 --- a/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java +++ b/nat/src/test/java/net/tomp2p/relay/UtilsNAT.java @@ -33,7 +33,6 @@ import net.tomp2p.peers.PeerAddress; import net.tomp2p.peers.PeerMap; import net.tomp2p.peers.PeerMapConfiguration; -import net.tomp2p.peers.PeerSocketAddress2; import net.tomp2p.rpc.RPC.Commands; public class UtilsNAT { @@ -211,10 +210,7 @@ public static PeerAddress createRandomAddress() throws UnknownHostException { public static PeerAddress createAddress(Number160 idSender, String inetSender, int tcpPortSender, int udpPortSender, boolean firewallUDP, boolean firewallTCP) throws UnknownHostException { - InetAddress inetSend = InetAddress.getByName(inetSender); - PeerSocketAddress2 peerSocketAddress = new PeerSocketAddress2(inetSend, tcpPortSender, udpPortSender); - PeerAddress n1 = new PeerAddress(idSender, peerSocketAddress, null, firewallTCP, firewallUDP, false, false, false, false, - PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES); + PeerAddress n1 = PeerAddress.create(idSender, inetSender, udpPortSender, tcpPortSender, udpPortSender + 1); return n1; } @@ -228,9 +224,9 @@ public static Message createRandomMessage() { message.command(Commands.values()[rnd.nextInt(Commands.values().length)].getNr()); message.type(Type.values()[rnd.nextInt(Type.values().length)]); message.recipientSocket(new InetSocketAddress(1234)); - message.recipient(new PeerAddress(new Number160(rnd), message.recipientSocket())); + message.recipient(PeerAddress.create(new Number160(rnd), message.recipientSocket())); message.senderSocket(new InetSocketAddress(5678)); - message.sender(new PeerAddress(new Number160(rnd), message.senderSocket())); + message.sender(PeerAddress.create(new Number160(rnd), message.senderSocket())); return message; } @@ -241,9 +237,7 @@ public static boolean messagesEqual(Message m1, Message m2) { && m1.command() == m2.command() && m1.sender().equals(m2.sender()) && m1.recipient().equals(m2.recipient()) - && m1.sender().tcpPort() == m2.sender().tcpPort() - && m1.sender().udpPort() == m2.sender().udpPort() - && m1.recipient().tcpPort() == m2.recipient().tcpPort() - && m1.recipient().udpPort() == m2.recipient().udpPort(); + && m1.sender().equals(m2.sender()) + && m1.recipient().equals(m2.recipient()); } } diff --git a/pom.xml b/pom.xml index a38dad26a..952675861 100644 --- a/pom.xml +++ b/pom.xml @@ -219,6 +219,9 @@ delombok + + UTF-8 + From 049902f22d7e98eddf85b5df75f67b857a6fdaad Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 18 Nov 2015 10:14:48 +0100 Subject: [PATCH 116/135] reduce verbosity in logger --- core/src/test/resources/logback.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/test/resources/logback.xml b/core/src/test/resources/logback.xml index 997001a56..5dd2cbb36 100644 --- a/core/src/test/resources/logback.xml +++ b/core/src/test/resources/logback.xml @@ -17,10 +17,10 @@ - - - - + + + + From e5f13f67332c83dcb928244f0d366929755c2be7 Mon Sep 17 00:00:00 2001 From: Sandy McArthur Date: Wed, 9 Dec 2015 17:47:01 -0500 Subject: [PATCH 117/135] Update class comment text Minor edit, not sure if this is actually correct but, what was there wasn't right. --- dht/src/main/java/net/tomp2p/dht/FutureGet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dht/src/main/java/net/tomp2p/dht/FutureGet.java b/dht/src/main/java/net/tomp2p/dht/FutureGet.java index 5c365c0ce..a8b982d40 100644 --- a/dht/src/main/java/net/tomp2p/dht/FutureGet.java +++ b/dht/src/main/java/net/tomp2p/dht/FutureGet.java @@ -25,7 +25,7 @@ import net.tomp2p.storage.Data; /** - * The future object for put() operations including routing. + * The future object for get() operations including routing. * * @author Thomas Bocek */ From 44bce7575f7e66d899efcab679ba1583c276adb0 Mon Sep 17 00:00:00 2001 From: Sandy McArthur Date: Fri, 11 Dec 2015 01:14:50 -0500 Subject: [PATCH 118/135] Avoids the slow reflection needed to resize an undersized array to hold all objects in the collection. --- core/src/main/java/net/tomp2p/storage/Data.java | 4 +++- core/src/main/java/net/tomp2p/storage/DataBuffer.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/tomp2p/storage/Data.java b/core/src/main/java/net/tomp2p/storage/Data.java index 95874e619..012d4d1d8 100644 --- a/core/src/main/java/net/tomp2p/storage/Data.java +++ b/core/src/main/java/net/tomp2p/storage/Data.java @@ -26,6 +26,7 @@ import java.security.SignatureException; import java.util.BitSet; import java.util.HashSet; +import java.util.List; import java.util.Set; import net.tomp2p.connection.DSASignatureFactory; @@ -816,7 +817,8 @@ public byte[] toBytes() { * @return The ByteBuffers that is the payload. We do not make a copy here */ public ByteBuffer[] toByteBuffers() { - return buffer.bufferList().toArray(new ByteBuffer[0]); + List byteBuffers = buffer.bufferList(); + return byteBuffers.toArray(new ByteBuffer[byteBuffers.size()]); } public PublicKey publicKey() { diff --git a/core/src/main/java/net/tomp2p/storage/DataBuffer.java b/core/src/main/java/net/tomp2p/storage/DataBuffer.java index 2dbf77969..e5ef4d5b1 100644 --- a/core/src/main/java/net/tomp2p/storage/DataBuffer.java +++ b/core/src/main/java/net/tomp2p/storage/DataBuffer.java @@ -161,7 +161,7 @@ public ByteBuf toByteBuf() { } else { final DataBuffer copy = shallowCopyIntern(); //wrap does a slice, so a derived buffer, not increasing ref count - return Unpooled.wrappedBuffer(copy.buffers.toArray(new ByteBuf[0])); + return Unpooled.wrappedBuffer(copy.buffers.toArray(new ByteBuf[copy.buffers.size()])); } } From a208822357716838810d4a158d9cd0d3cdc88cdd Mon Sep 17 00:00:00 2001 From: Sandy McArthur Date: Fri, 11 Dec 2015 12:43:58 -0500 Subject: [PATCH 119/135] Update logic in NATTypeDetection.twoOutOfThreeSame Suggested fix for issue #121 --- .../java/net/tomp2p/holep/NATTypeDetection.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java index f00b5278f..b5cb8c229 100644 --- a/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java +++ b/nat/src/main/java/net/tomp2p/holep/NATTypeDetection.java @@ -130,16 +130,7 @@ private boolean checkCompleteMessage(FutureResponse futureResponse) { } private static boolean twoOutOfThreeSame(int i1, int i2, int i3, int k1, int k2, int k3) { - if (i1 == k1 || i2 == k2) { - return true; - } - if (i1 == k1 || i3 == k3) { - return true; - } - if (i2 == k2 || i3 == k3) { - return true; - } - return false; + return (i1 == k1 && i2 == k2) || (i1 == k1 && i3 == k3) || (i2 == k2 && i3 == k3); } private static boolean sequential(int i1, int i2, int i3, int k1, int k2, int k3, int tolerance) { @@ -166,4 +157,4 @@ private static NATType checkNATType(final int seenAsPort1, final int seenAsPort2 LOG.debug("Symmetric NAT detected (assumed since all other tests failed)"); return NATType.NON_PRESERVING_OTHER; } -} \ No newline at end of file +} From af137fe5639e2209a7aa59386ba0b1c54ac6cc7e Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 15:48:52 +0100 Subject: [PATCH 120/135] updated project name and fixed testcase --- all/pom.xml | 2 +- dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java | 2 +- examples/pom.xml | 2 +- nat/pom.xml | 2 +- social/pom.xml | 2 +- storage/pom.xml | 2 +- tracker/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 1affd99b1..ed2d37b28 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -19,7 +19,7 @@ tomp2p-all jar - TomP2P all-in-one + TomP2P All-in-One diff --git a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java index 87284f8a8..d76d971a3 100644 --- a/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java +++ b/dht/src/test/java/net/tomp2p/dht/TestStorageDHT.java @@ -94,7 +94,7 @@ public void testNeigbhorBloomfilter() throws Exception { PeerDHT recv1 = null; try { sender = new PeerBuilderDHT(new PeerBuilder(new Number160("0x50")).p2pId(55).ports(2424).start()).start(); - PeerAddress[] pa = UtilsDHT2.createDummyAddress(300, PORT_TCP, PORT_UDP, PORT_UDP + 1); + PeerAddress[] pa = UtilsDHT2.createDummyAddress(300, PORT_UDP, PORT_TCP, PORT_UDP + 1); for (int i = 0; i < pa.length; i++) { sender.peerBean().peerMap().peerFound(pa[i], null, null, null); } diff --git a/examples/pom.xml b/examples/pom.xml index 9859d74f8..0930f7aee 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -24,7 +24,7 @@ tomp2p-examples - TomP2P examples + TomP2P Examples jar diff --git a/nat/pom.xml b/nat/pom.xml index c9c02c4a5..8a2fd02e0 100644 --- a/nat/pom.xml +++ b/nat/pom.xml @@ -17,7 +17,7 @@ tomp2p-nat - TomP2P nat + TomP2P NAT jar diff --git a/social/pom.xml b/social/pom.xml index 6d1bc3056..cf6afd1ba 100644 --- a/social/pom.xml +++ b/social/pom.xml @@ -24,7 +24,7 @@ tomp2p-social - TomP2P social + TomP2P Social jar diff --git a/storage/pom.xml b/storage/pom.xml index bad1479fa..cd2c74718 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -24,7 +24,7 @@ tomp2p-storage - TomP2P storage + TomP2P Storage jar diff --git a/tracker/pom.xml b/tracker/pom.xml index ea499273b..88d54d463 100644 --- a/tracker/pom.xml +++ b/tracker/pom.xml @@ -24,7 +24,7 @@ tomp2p-tracker - TomP2P tracker + TomP2P Tracker jar From 7fb6654a82a90de13e68cf583ebc61d9919c1cb7 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 16:13:53 +0100 Subject: [PATCH 121/135] travis-ci shows buffer overflow, trying to change the jdk to 8 *** buffer overflow detected ***: /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java terminated ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f1928ff6e57] /lib/x86_64-linux-gnu/libc.so.6(+0x108d50)[0x7f1928ff5d50] /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/libnet.so(Java_java_net_Inet4AddressImpl_getLocalHostName+0x190)[0x7f191cd7a9a0] [0x7f191d012d98] --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8e6a407a0..26d5aa730 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: java jdk: - - openjdk7 + - openjdk8 #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From e0c4a5ed70f3a3937189601f630b44f2b9ccfebc Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 16:40:47 +0100 Subject: [PATCH 122/135] there is no openjdk8, just the oraclejdk8 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 26d5aa730..0a2fecbd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: java jdk: - - openjdk8 + - oraclejdk8 #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From b96eb84f14084e799f564292e4ce4a6912aaba93 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 16:53:48 +0100 Subject: [PATCH 123/135] trying openjdk7 again --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0a2fecbd5..8e6a407a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: java jdk: - - oraclejdk8 + - openjdk7 #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From 62ce904e1111289d265e7c61eff2460e587aa129 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 18:30:20 +0100 Subject: [PATCH 124/135] shorten hostname due to jdk7 bug --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8e6a407a0..b2cb944cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,14 @@ language: java jdk: - openjdk7 + +sudo: false + +before_install: + - cat /etc/hosts # optionally check the content *before* + - sudo hostname "$(hostname | cut -c1-63)" + - sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts + - cat /etc/hosts # optionally check the content *after* #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From a43d0e8aaad50ee352a4b0bf17db43114ba4821d Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 18:31:55 +0100 Subject: [PATCH 125/135] set sudo to required --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b2cb944cf..7c46a19bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: java jdk: - openjdk7 -sudo: false +sudo: required before_install: - cat /etc/hosts # optionally check the content *before* From afcc0d841fe243498b06b944c96a8d42e1a83b7b Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 18:45:03 +0100 Subject: [PATCH 126/135] set buffer for sender and receiver for input and output. If this is not set, the manual testcases for NAT may randomly fail --- core/src/main/java/net/tomp2p/connection/ChannelCreator.java | 4 ++-- core/src/main/java/net/tomp2p/connection/ChannelServer.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java index 9251017e5..6f840f669 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelCreator.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelCreator.java @@ -150,8 +150,8 @@ public ChannelFuture createUDP(final boolean broadcast, final Map() { @Override From 5f78b34ceb5ac02832a4ef53b61440cb658041a7 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Tue, 5 Jan 2016 19:06:17 +0100 Subject: [PATCH 127/135] try upd without support for broadcasting --- .../main/java/net/tomp2p/connection/ChannelServer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServer.java b/core/src/main/java/net/tomp2p/connection/ChannelServer.java index a0bfa63eb..a8eb9b9db 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServer.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServer.java @@ -159,9 +159,14 @@ private void listenAny() { } final InetSocketAddress udpSocket = new InetSocketAddress(channelServerConfiguration.ports().udpPort()); - final boolean udpStart = startupUDP(udpSocket, channelServerConfiguration, true); + final boolean udpStart = startupUDP(udpSocket, channelServerConfiguration, true); if(!udpStart) { - LOG.warn("cannot bind UDP on socket {}",udpSocket); + final boolean udpStart2 = startupUDP(udpSocket, channelServerConfiguration, false); + if(!udpStart2) { + LOG.warn("cannot bind UDP on socket at all {}", udpSocket); + } else { + LOG.warn("can only bind to UDP without broadcast support {}", udpSocket); + } } else { LOG.info("Listening UDP on socket {}",udpSocket); } From ac7ef77aea45ec4a7b57984fab2f66471dbed339 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 6 Jan 2016 13:36:47 +0100 Subject: [PATCH 128/135] travis issue with UDP --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7c46a19bd..3fe83fce4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ before_install: - sudo hostname "$(hostname | cut -c1-63)" - sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts - cat /etc/hosts # optionally check the content *after* + - ifconfig #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From 1ab3441e584e6ab84a1c6cd226d1421f5bd49e8f Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 6 Jan 2016 13:42:41 +0100 Subject: [PATCH 129/135] travis issue with UDP --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3fe83fce4..b333cc51d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ before_install: - sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts - cat /etc/hosts # optionally check the content *after* - ifconfig + - apt-cache search nc | grep netcat + - nc -lu 4444 #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From 53f64522ad8acfbfc8d3163f1df54a4a4e6fb215 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 6 Jan 2016 14:09:18 +0100 Subject: [PATCH 130/135] If bcast and inet are the same, udp shows warning --- .../net/tomp2p/connection/ChannelServer.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServer.java b/core/src/main/java/net/tomp2p/connection/ChannelServer.java index a8eb9b9db..3cbfa7fd5 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServer.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServer.java @@ -16,6 +16,7 @@ package net.tomp2p.connection; +import com.sun.javafx.scene.control.skin.VirtualFlow; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; @@ -34,6 +35,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -175,6 +177,19 @@ private void listenAny() { //this method has blocking calls in it private void listenSpecificInetAddresses(DiscoverResults discoverResults) { + /** + * Travis-ci has the same inet address as the broadcast adress, handle it properly. + * + * eth0 Link encap:Ethernet HWaddr 42:01:0a:f0:00:19 + * inet addr:10.240.0.25 Bcast:10.240.0.25 Mask:255.255.255.255 + * UP BROADCAST RUNNING MULTICAST MTU:1460 Metric:1 + * RX packets:849 errors:0 dropped:0 overruns:0 frame:0 + * TX packets:914 errors:0 dropped:0 overruns:0 carrier:0 + * collisions:0 txqueuelen:1000 + * RX bytes:1080397 (1.0 MB) TX bytes:123816 (123.8 KB) + */ + final List broadcastAddresses = new ArrayList(); + for (InetAddress inetAddress : discoverResults.newBroadcastAddresses()) { InetSocketAddress udpBroadcastSocket = new InetSocketAddress(inetAddress, channelServerConfiguration.ports() .udpPort()); @@ -184,6 +199,7 @@ private void listenSpecificInetAddresses(DiscoverResults discoverResults) { if (udpStartBroadcast) { //if one broadcast address was found, then we don't need to bind to 0.0.0.0 broadcastAddressSupported = true; + broadcastAddresses.add(udpBroadcastSocket); LOG.info("Listening on broadcast address: {} on port udp: {}" , udpBroadcastSocket, channelServerConfiguration.ports().udpPort()); } else { @@ -222,8 +238,12 @@ private void listenSpecificInetAddresses(DiscoverResults discoverResults) { //as we are listening to anything on UDP, we don't need to listen to any other interfaces if(!udpStartBroadcast) { - InetSocketAddress udpSocket = new InetSocketAddress(inetAddress, + InetSocketAddress udpSocket = new InetSocketAddress(inetAddress, channelServerConfiguration.ports().udpPort()); + //if we already bound to the inetaddress as bcast and inet are the same + if(broadcastAddresses.contains(udpSocket)) { + return; + } boolean udpStart = startupUDP(udpSocket, channelServerConfiguration, false); if(!udpStart) { LOG.warn("cannot bind UDP on socket {}",udpSocket); From b11a8ce5effa5e644468ee37181f3af2b942c1b8 Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 6 Jan 2016 14:09:33 +0100 Subject: [PATCH 131/135] removed test code --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b333cc51d..7c46a19bd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,6 @@ before_install: - sudo hostname "$(hostname | cut -c1-63)" - sed -e "s/^\\(127\\.0\\.0\\.1.*\\)/\\1 $(hostname | cut -c1-63)/" /etc/hosts | sudo tee /etc/hosts - cat /etc/hosts # optionally check the content *after* - - ifconfig - - apt-cache search nc | grep netcat - - nc -lu 4444 #solved in pom.xml #env: MAVEN_OPTS="-Dio.netty.leakDetectionLevel=paranoid" From 5a36b1a122274f3d0093e3373b64ffaf08658fae Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Wed, 6 Jan 2016 14:15:24 +0100 Subject: [PATCH 132/135] fix imports --- core/src/main/java/net/tomp2p/connection/ChannelServer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/ChannelServer.java b/core/src/main/java/net/tomp2p/connection/ChannelServer.java index 3cbfa7fd5..de39717a8 100644 --- a/core/src/main/java/net/tomp2p/connection/ChannelServer.java +++ b/core/src/main/java/net/tomp2p/connection/ChannelServer.java @@ -16,7 +16,6 @@ package net.tomp2p.connection; -import com.sun.javafx.scene.control.skin.VirtualFlow; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; From ac442ae42f025941c15bb4097331f1f77a90f05a Mon Sep 17 00:00:00 2001 From: Thomas Bocek Date: Mon, 25 Jan 2016 13:21:44 +0100 Subject: [PATCH 133/135] adding testcase to test closing of permament TCP connection --- .../net/tomp2p/connection/Reservation.java | 12 +++ .../java/net/tomp2p/p2p/TestConnection.java | 80 ++++++++++++++++++- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/tomp2p/connection/Reservation.java b/core/src/main/java/net/tomp2p/connection/Reservation.java index ccaba21df..676f83ca9 100644 --- a/core/src/main/java/net/tomp2p/connection/Reservation.java +++ b/core/src/main/java/net/tomp2p/connection/Reservation.java @@ -103,6 +103,18 @@ public Reservation(final EventLoopGroup workerGroup, final ChannelClientConfigur this.channelClientConfiguration = channelClientConfiguration; this.peerBean = peerBean; } + + public int availablePermitsUDP() { + return semaphoreUPD.availablePermits(); + } + + public int availablePermitsTCP() { + return semaphoreTCP.availablePermits(); + } + + public int availablePermitsPermanentTCP() { + return semaphorePermanentTCP.availablePermits(); + } /** * @return The pending number of requests that are scheduled but not diff --git a/core/src/test/java/net/tomp2p/p2p/TestConnection.java b/core/src/test/java/net/tomp2p/p2p/TestConnection.java index fdda54b3f..e5db2fc75 100644 --- a/core/src/test/java/net/tomp2p/p2p/TestConnection.java +++ b/core/src/test/java/net/tomp2p/p2p/TestConnection.java @@ -7,14 +7,17 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Random; +import java.util.concurrent.CountDownLatch; import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.connection.ChannelServerConfiguration; import net.tomp2p.connection.PipelineFilter; import net.tomp2p.connection.StandardProtocolFamily; +import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureBootstrap; import net.tomp2p.futures.FutureDirect; +import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FuturePeerConnection; import net.tomp2p.message.CountConnectionOutboundHandler; import net.tomp2p.peers.Number160; @@ -29,7 +32,6 @@ import org.junit.rules.TestWatcher; import org.junit.runner.Description; -//TODO: find out why the shutdown takes 2 seconds public class TestConnection { @Rule @@ -119,4 +121,80 @@ public Object reply(PeerAddress sender, Object request) throws Exception { } } } + + @Test + public void testPermanentConnection() throws Exception { + Random rnd = new Random(42); + Peer peer1 = null; + Peer peer2 = null; + try { + + Bindings b1 = new Bindings().addProtocol(StandardProtocolFamily.INET).addAddress(InetAddress.getByName("127.0.0.1")); + Bindings b2 = new Bindings().addProtocol(StandardProtocolFamily.INET).addAddress(InetAddress.getByName("127.0.0.1")); + + peer1 = new PeerBuilder(new Number160(rnd)).ports(4005).bindings(b1).start(); + peer2 = new PeerBuilder(new Number160(rnd)).ports(4006).bindings(b2).start(); + + peer2.objectDataReply(new ObjectDataReply() { + @Override + public Object reply(PeerAddress sender, Object request) throws Exception { + return "world!"; + } + }); + // keep the connection for 20s alive. Setting -1 means to keep it + // open as long as possible + FutureBootstrap masterAnother = peer1.bootstrap().peerAddress(peer2.peerAddress()).start(); + FutureBootstrap anotherMaster = peer2.bootstrap().peerAddress(peer1.peerAddress()).start(); + masterAnother.awaitUninterruptibly(); + anotherMaster.awaitUninterruptibly(); + + int before = peer1.connectionBean().reservation().availablePermitsPermanentTCP(); + final FuturePeerConnection fpc = peer1.createPeerConnection(peer2.peerAddress()); + + // fpc.awaitUninterruptibly(); + // PeerConnection peerConnection = fpc.peerConnection(); + String sentObject = "Hello"; + FutureDirect fd = peer1.sendDirect(fpc).object(sentObject).start(); + fd.awaitUninterruptibly(); + + Assert.assertEquals(before - 1, peer1.connectionBean().reservation().availablePermitsPermanentTCP()); + + peer2.shutdown().await(); + + fpc.peerConnection().closeFuture().addListener(new BaseFutureAdapter>() { + @Override + public void operationComplete(FutureDone future) throws Exception { + fpc.peerConnection().close().await(); + } + }); + //TODO: make this not wait + Thread.sleep(1000); + Assert.assertEquals(before, peer1.connectionBean().reservation().availablePermitsPermanentTCP()); + + // we reuse the connection + /*long start = System.currentTimeMillis(); + System.out.println("send " + sentObject); + fd = peer1.sendDirect(fpc).object(sentObject).start(); + fd.awaitUninterruptibly(); + System.err.println(fd.failedReason()); + Assert.assertEquals(true, fd.isSuccess()); + System.err.println(fd.failedReason()); + System.out.println("received " + fd.object() + " connections: " + + ccohTCP.total()); + // now we don't want to keep the connection open anymore: + double duration = (System.currentTimeMillis() - start) / 1000d; + System.out.println("Send and get in s:" + duration);*/ + fpc.close().await(); + System.out.println("done"); + } finally { + if (peer1 != null) { + peer1.shutdown().await(); + System.out.println("done1"); + } + if (peer2 != null) { + peer2.shutdown().await(); + System.out.println("done2"); + } + } + } } From 4499ff62dd9d835ca85e0a0757238201b12943e6 Mon Sep 17 00:00:00 2001 From: Dyslesiq Date: Wed, 9 Mar 2016 23:40:39 +0100 Subject: [PATCH 134/135] Added TCP/UDP switch to BootstrapBuilder --- .../tomp2p/p2p/builder/BootstrapBuilder.java | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java index ecde6be4f..17b2c5d3e 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/BootstrapBuilder.java @@ -20,6 +20,7 @@ import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; +import net.tomp2p.connection.DefaultConnectionConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,11 +45,11 @@ /** * Bootstraps to a known peer. First, channels are reserved, then discover(PeerAddress) is called to verify this Internet * connection settings using the "peerAddress" argument . Then the routing is initiated to the peers specified in - * "bootstrapTo". Please be aware that in order to boostrap, you need to know the peer ID of all peers in the "bootstrapTo" collection. - * Passing Number160.ZERO does *not* work. + * "bootstrapTo". Please be aware that in order to bootstrap, you need to know the peer ID of all peers in the + * "bootstrapTo" collection. * Passing Number160.ZERO does *not* work. */ +public class BootstrapBuilder extends DefaultConnectionConfiguration { -public class BootstrapBuilder { private static final Logger logger = LoggerFactory.getLogger(BootstrapBuilder.class); private static final FutureBootstrap FUTURE_BOOTSTRAP_SHUTDOWN = new FutureWrappedBootstrap() @@ -76,7 +77,7 @@ public class BootstrapBuilder { public BootstrapBuilder(Peer peer) { this.peer = peer; } - + public PeerAddress peerAddress() { return peerAddress; } @@ -111,18 +112,45 @@ public InetAddress inetAddress() { return inetAddress; } + /** + * In case the peerID is not known, only the known inet address can be specified. + * + * If the inetAddress is set and {@link #bootstrapTo()} and {@link #peerAddress()} are null, a ping will be + * triggered first to discover the distant peerID, then, on success, the normal bootstrap will continue. + * + * The discovered Peer (with its ID) will be accessible through {@link #bootstrapTo()}. + * + * @param inetAddress the address to bootstrap to. + * @return the builder instance + */ public BootstrapBuilder inetAddress(InetAddress inetAddress) { this.inetAddress = inetAddress; return this; } - + + /** + * See {@link #inetAddress(java.net.InetAddress)} for details. + * + * Use given socket ports instead of default ports to reach the distant peer. + * + * @param socket the socket address to bootstrap to + * @return the builder instance + */ public BootstrapBuilder inetSocketAddress(InetSocketAddress socket) { this.inetAddress = socket.getAddress(); this.portTCP = socket.getPort(); this.portUDP = socket.getPort(); return this; } - + + /** + * See {@link #inetAddress(java.net.InetAddress)} for details. + * + * Use given socket ports instead of default ports to reach the distant peer. + * + * @param socket the PeerSocket4Address to bootstrap to + * @return the builder instance + */ public BootstrapBuilder peerSocketAddress(PeerSocket4Address socket) { this.inetAddress = socket.ipv4().toInetAddress(); this.portTCP = socket.tcpPort(); @@ -205,7 +233,14 @@ private FutureBootstrap bootstrap() { final FutureWrappedBootstrap>> result = new FutureWrappedBootstrap>>(); result.bootstrapTo(bootstrapTo); int conn = routingConfiguration.parallel(); - FutureChannelCreator fcc = peer.connectionBean().reservation().create(conn, 0); + FutureChannelCreator fcc; + + if (this.forceTCP) { + fcc = peer.connectionBean().reservation().create(0, conn); + } else { + //The actual bootstrap defaults to UDP + fcc = peer.connectionBean().reservation().create(conn, 0); + } Utils.addReleaseListener(fcc, result); fcc.addListener(new BaseFutureAdapter() { @Override @@ -236,7 +271,14 @@ static RoutingBuilder createBuilder(RoutingConfiguration routingConfiguration, b private FutureWrappedBootstrap bootstrapPing(PeerAddress address) { final FutureWrappedBootstrap result = new FutureWrappedBootstrap(); - final FuturePing futurePing = peer.ping().peerAddress(address).tcpPing().start(); + + final FuturePing futurePing; + if (this.forceUDP) { + futurePing = peer.ping().peerAddress(address).start(); + } else { + //Bootstrap ping defaults to TCP + futurePing = peer.ping().peerAddress(address).tcpPing().start(); + } futurePing.addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FuturePing future) throws Exception { From d4fbf47184ebb56e7b9ae4ce3f5c80d111244892 Mon Sep 17 00:00:00 2001 From: Dyslesiq Date: Wed, 9 Mar 2016 23:42:47 +0100 Subject: [PATCH 135/135] Added TCP/UDP switch to DiscoverBuilder. Added/Corected comments. Corrected a bug regarding internal ip setup on manual port forwarding. --- .../net/tomp2p/futures/FutureDiscover.java | 8 +- .../tomp2p/p2p/builder/DiscoverBuilder.java | 247 ++++++++++-------- .../src/main/java/net/tomp2p/rpc/PingRPC.java | 4 +- 3 files changed, 145 insertions(+), 114 deletions(-) diff --git a/core/src/main/java/net/tomp2p/futures/FutureDiscover.java b/core/src/main/java/net/tomp2p/futures/FutureDiscover.java index 4a082a04f..e7e56d69c 100644 --- a/core/src/main/java/net/tomp2p/futures/FutureDiscover.java +++ b/core/src/main/java/net/tomp2p/futures/FutureDiscover.java @@ -75,7 +75,7 @@ public void operationComplete(final FutureDiscover future) throws Exception { } /** - * Gets called if the discovery was a success and an other peer could ping us with TCP and UDP. + * Gets called if the discovery was a success and an other peer could ping us with TCP and/or UDP. * * @param ourPeerAddress * The peerAddress of our server @@ -187,9 +187,9 @@ private DiscoverTimeoutTask(PeerAddress serverPeerAddress) { @Override public void run() { - failed(serverPeerAddress, "Timeout in Discover: " + - (System.currentTimeMillis() - start) + "ms. Seems like pingTCPProbe or pingUDPProbe did not " + - "succeed in time. However my address reported from pingTCPDiscover is " + serverPeerAddress); + failed(serverPeerAddress, "Timeout in Discover: " + (System.currentTimeMillis() - start) + + "ms. Seems like pingTCPProbe or pingUDPProbe did not succeed in time." + + " However my address reported from pingDiscover is " + serverPeerAddress); } } diff --git a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java index 6c02eae50..498885ddc 100644 --- a/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java +++ b/core/src/main/java/net/tomp2p/p2p/builder/DiscoverBuilder.java @@ -18,10 +18,8 @@ import java.net.InetAddress; import java.util.Collection; - import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelCreator; -import net.tomp2p.connection.ConnectionConfiguration; import net.tomp2p.connection.DefaultConnectionConfiguration; import net.tomp2p.connection.DiscoverNetworks; import net.tomp2p.connection.DiscoverResults; @@ -29,9 +27,7 @@ import net.tomp2p.futures.BaseFutureAdapter; import net.tomp2p.futures.FutureChannelCreator; import net.tomp2p.futures.FutureDiscover; -import net.tomp2p.futures.FutureDone; import net.tomp2p.futures.FutureResponse; -import net.tomp2p.futures.Futures; import net.tomp2p.message.Message.Type; import net.tomp2p.p2p.Peer; import net.tomp2p.p2p.PeerReachable; @@ -44,7 +40,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class DiscoverBuilder { +public class DiscoverBuilder extends DefaultConnectionConfiguration { final private static Logger LOG = LoggerFactory.getLogger(DiscoverBuilder.class); final private static FutureDiscover FUTURE_DISCOVER_SHUTDOWN = new FutureDiscover() @@ -62,10 +58,8 @@ public class DiscoverBuilder { private int discoverTimeoutSec = 5; - private ConnectionConfiguration configuration; - private FutureDiscover futureDiscover; - + private boolean expectManualForwarding; public DiscoverBuilder(Peer peer) { @@ -160,17 +154,22 @@ public boolean isExpectManualForwarding() { public DiscoverBuilder expectManualForwarding() { return setExpectManualForwarding(true); } - + public DiscoverBuilder setExpectManualForwarding(boolean expectManualForwarding) { this.expectManualForwarding = expectManualForwarding; return this; } + /** + * @return The future discover. This future holds also the real ID of the peer we send the discover request + */ public FutureDiscover start() { if (peer.isShutdown()) { return FUTURE_DISCOVER_SHUTDOWN; } - + if (forceTCP && forceUDP) { + throw new IllegalArgumentException("Only one of 'forceTCP' or 'forceUDP' can be chosen."); + } if (peerAddress == null && inetAddress != null) { PeerSocket4Address psa = PeerSocket4Address.builder().ipv4(IPv4.fromInet4Address(inetAddress)).tcpPort(portTCP).udpPort(portUDP).build(); peerAddress = PeerAddress.builder().ipv4Socket(psa).peerId(Number160.ZERO).build(); @@ -178,13 +177,10 @@ public FutureDiscover start() { if (peerAddress == null) { throw new IllegalArgumentException("Peer address or inet address required."); } - if (configuration == null) { - configuration = new DefaultConnectionConfiguration(); - } if (futureDiscover == null) { futureDiscover = new FutureDiscover(); } - return discover(peerAddress, configuration, futureDiscover); + return discover(peerAddress); } /** @@ -194,17 +190,25 @@ public FutureDiscover start() { * * @param peerAddress * The peer address. Since pings are used the peer ID can be Number160.ZERO - * @return The future discover. This future holds also the real ID of the peer we send the discover request + * @return The future discover. */ - private FutureDiscover discover(final PeerAddress peerAddress, final ConnectionConfiguration configuration, - final FutureDiscover futureDiscover) { - FutureChannelCreator fcc = peer.connectionBean().reservation().create(1, 2); + private FutureDiscover discover(final PeerAddress peerAddress) { + FutureChannelCreator fcc; + if (forceUDP) { + //Only reserve udp channels + fcc = peer.connectionBean().reservation().create(2, 0); + } else if (forceTCP) { + //Only reserve tcp channels + fcc = peer.connectionBean().reservation().create(0, 2); + } else { + fcc = peer.connectionBean().reservation().create(1, 2); + } Utils.addReleaseListener(fcc, futureDiscover); fcc.addListener(new BaseFutureAdapter() { @Override public void operationComplete(final FutureChannelCreator future) throws Exception { if (future.isSuccess()) { - discover(futureDiscover, peerAddress, future.channelCreator(), configuration); + pingDiscover(peerAddress, future.channelCreator()); } else { futureDiscover.failed(future); } @@ -214,73 +218,73 @@ public void operationComplete(final FutureChannelCreator future) throws Exceptio } /** - * Needs 3 connections. Cleans up ChannelCreator, which means they will be released. + * Starts the discovery process. + * + * First launch a pingDiscover to setup our addresses then probe our reachability. + * + * Cleans up ChannelCreator, which means they will be released. * * @param peerAddress * @param cc * @return */ - private void discover(final FutureDiscover futureDiscover, final PeerAddress peerAddress, - final ChannelCreator cc, final ConnectionConfiguration configuration) { - LOG.debug("starting discover to {}",peerAddress); - final FutureDone pingDone = new FutureDone(); + private void pingDiscover(final PeerAddress peerAddress, final ChannelCreator cc) { + LOG.debug("starting discover to {}", peerAddress); - peer.pingRPC().addPeerReachableListener(new PeerReachable() { - private volatile boolean changedUDP = false; - private volatile boolean changedTCP = false; + final PeerReachable reachableListener = new PeerReachable() { @Override - public void peerWellConnected(final PeerAddress peerAddress, final PeerAddress reporter, final boolean tcp) { - pingDone.addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureDone future) throws Exception { - if (tcp) { - futureDiscover.discoveredTCP(); - changedTCP = true; - LOG.debug("TCP discovered"); - } else { - futureDiscover.discoveredUDP(); - changedUDP = true; - LOG.debug("UDP discovered"); - } - if (changedTCP && changedUDP) { - futureDiscover.done(peerAddress, reporter); - } - } - }); - + public void peerWellConnected(final PeerAddress peerAddress, final PeerAddress reporter, + final boolean tcp) { + LOG.info("peerWellConnected."); + if (tcp) { + futureDiscover.discoveredTCP(); + LOG.debug("TCP discovered"); + } else { + futureDiscover.discoveredUDP(); + LOG.debug("UDP discovered"); + } + if (futureDiscover.isDiscoveredTCP() && forceTCP) { + //If we forced TCP, assume we only wait for the TCP response to finish + futureDiscover.done(peerAddress, reporter); + } else if (futureDiscover.isDiscoveredUDP() && forceUDP) { + //If we forced UDP, assume we only wait for the UDP response to finish + futureDiscover.done(peerAddress, reporter); + } else if (futureDiscover.isDiscoveredTCP() && futureDiscover.isDiscoveredUDP()) { + futureDiscover.done(peerAddress, reporter); + } } - }); + }; + peer.pingRPC().addPeerReachableListener(reachableListener); + //Shoudn't the Reachable listener be removed once done() ? + + final FutureResponse futureResponse; + if (forceUDP) { + futureResponse = peer.pingRPC().pingUDPDiscover(peerAddress, cc, this); + } else { + //ping discover by default with tcp + futureResponse = peer.pingRPC().pingTCPDiscover(peerAddress, cc, this); + } - final FutureResponse futureResponseTCP = peer.pingRPC().pingTCPDiscover(peerAddress, cc, - configuration); - - futureResponseTCP.addListener(new BaseFutureAdapter() { + futureResponse.addListener(new BaseFutureAdapter() { @Override public void operationComplete(FutureResponse future) throws Exception { PeerAddress serverAddress = peer.peerBean().serverPeerAddress(); - if (futureResponseTCP.isSuccess() && futureResponseTCP.responseMessage().type() == Type.NOT_FOUND) { + if (futureResponse.isSuccess() && futureResponse.responseMessage().type() == Type.NOT_FOUND) { //this was a ping to myself. This is pointless - futureDiscover.failed("FutureDiscover to yourself", - futureResponseTCP); - return; - } - else if (futureResponseTCP.isSuccess()) { - //now we know our internal address, set it as it could be a wrong one, e.g. 127.0.0.1 - serverAddress = serverAddress.withIpv4Socket(futureResponseTCP.responseMessage().recipient().ipv4Socket()); - - Collection tmp = futureResponseTCP.responseMessage().neighborsSet(0) + futureDiscover.failed("FutureDiscover to yourself", futureResponse); + } else if (futureResponse.isSuccess()) { + Collection tmp = futureResponse.responseMessage().neighborsSet(0) .neighbors(); - futureDiscover.reporter(futureResponseTCP.responseMessage().sender()); + futureDiscover.reporter(futureResponse.responseMessage().sender()); if (tmp.size() == 1) { PeerAddress seenAs = tmp.iterator().next(); LOG.info("This peer is seen as {} by peer {}. This peer sees itself as {}.", seenAs, peerAddress, peer.peerAddress()); if (!peer.peerAddress().ipv4Socket().equalsWithoutPorts(seenAs.ipv4Socket())) { - // check if we have this interface in that we can - // listen to + // check if we have this interface in that we can listen to Bindings bindings2 = new Bindings().addAddress(seenAs.ipv4Socket().ipv4().toInetAddress()); - + DiscoverResults discoverResults = DiscoverNetworks.discoverInterfaces(bindings2); String status = discoverResults.status(); LOG.info("2nd interface discovery: {}", status); @@ -290,75 +294,102 @@ else if (futureResponseTCP.isSuccess()) { peer.peerBean().serverPeerAddress(serverAddress); LOG.info("This peer had the wrong interface. Changed it to {}.", serverAddress); } else { - // now we know our internal IP, where we receive - // packets + // now we know our internal IP, where we receive packets final Ports ports = peer.connectionBean().channelServer().channelServerConfiguration().portsForwarding(); if (ports.isManualPort()) { final PeerAddress serverAddressOrig = serverAddress; - PeerSocket4Address serverSocket = serverAddress.ipv4Socket(); + PeerSocket4Address serverSocket = serverAddress.ipv4Socket(); serverSocket = serverSocket.withTcpPort(ports.tcpPort()).withUdpPort(ports.udpPort()); serverSocket = serverSocket.withIpv4(seenAs.ipv4Socket().ipv4()); //manual port forwarding detected, set flag - peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket).withIpInternalSocket(serverAddressOrig.ipv4Socket())); + peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket). + withNet4Internal(true).withIpInternalSocket(serverAddressOrig.ipv4Socket())); LOG.info("manual ports, change it to: {}", serverAddress); } else if(expectManualForwarding) { final PeerAddress serverAddressOrig = serverAddress; PeerSocket4Address serverSocket = serverAddress.ipv4Socket(); serverSocket = serverSocket.withIpv4(seenAs.ipv4Socket().ipv4()); - peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket).withIpInternalSocket(serverAddressOrig.ipv4Socket())); + peer.peerBean().serverPeerAddress(serverAddress.withIpv4Socket(serverSocket) + .withNet4Internal(true).withIpInternalSocket(serverAddressOrig.ipv4Socket())); LOG.info("we were manually forwarding, change it to: {}", serverAddress); - } - else { + } else { // we need to find a relay, because there is a NAT in the way. // we cannot use futureResponseTCP.responseMessage().recipient() as this may return also IPv6 addresses LOG.info("We are most likely behind NAT, try to UPNP, NATPMP or relay. PeerAddress: {}, ServerAddress: {}, Seen as: {}" + peerAddress, serverAddress, seenAs); futureDiscover.externalHost("We are most likely behind NAT, try to UPNP, NATPMP or relay. Using peerAddress " + peerAddress, serverAddress.ipv4Socket(), seenAs.ipv4Socket()); - return; } } } - // else -> we announce exactly how the other peer sees - // us - FutureResponse fr1 = peer.pingRPC().pingTCPProbe(peerAddress, cc, - configuration); - fr1.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if(future.isFailed() ) { - LOG.warn("FutureDiscover (2): We need at least the TCP connection {} - {}", future, futureDiscover.failedReason()); - futureDiscover.failed("FutureDiscover (2): We need at least the TCP connection", future); - } - } - }); - FutureResponse fr2 = peer.pingRPC().pingUDPProbe(peerAddress, cc, - configuration); - fr2.addListener(new BaseFutureAdapter() { - @Override - public void operationComplete(FutureResponse future) throws Exception { - if(future.isFailed() ) { - LOG.warn("FutureDiscover (2): UDP failed connection {} - {}", future, futureDiscover.failedReason()); - } - } - }); - Futures.whenAll(fr1, fr2).addListener(new BaseFutureAdapter>() { - @Override - public void operationComplete(FutureDone future) throws Exception { - pingDone.done(); - } - }); - // from here we probe, set the timeout here + //Ask distant peer to reach us now that our internal and external addresses are (hopefully) correct + pingProbe(cc); + // from here we probe, set the timeout futureDiscover.timeout(serverAddress, peer.connectionBean().timer(), discoverTimeoutSec); - return; } else { futureDiscover.failed("Peer " + peerAddress + " did not report our IP address."); - return; } } else { - futureDiscover.failed("FutureDiscover (1): We need at least the TCP connection", - futureResponseTCP); - return; + futureDiscover.failed("FutureDiscover (1): we need at least the first pingDiscover", futureResponse); } } }); } + + /** + * Once the pingDiscover succeeded, probe our reachability with either TCP, UDP or both. + * + * @param cc + */ + private void pingProbe(final ChannelCreator cc) { + if (forceUDP) { + //Only probe with UDP and finish discovery on success + FutureResponse frUdp = peer.pingRPC().pingUDPProbe(peerAddress, cc, DiscoverBuilder.this); + frUdp.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if (future.isFailed()) { + LOG.warn("FutureDiscover (2): We need the UDP connection with forceUDP {} - {}", + future, futureDiscover.failedReason()); + futureDiscover.failed("FutureDiscover (2): We need the UDP connection with forceUDP", future); + } + } + }); + } else if (forceTCP) { + //Only probe with TCP and finish discovery on success + FutureResponse frTcp = peer.pingRPC().pingTCPProbe(peerAddress, cc, DiscoverBuilder.this); + frTcp.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if (future.isFailed()) { + LOG.warn("FutureDiscover (2): We need the TCP connection with forceTCP {} - {}", + future, futureDiscover.failedReason()); + futureDiscover.failed("FutureDiscover (2): We need the TCP connection with forceTCP", future); + } + } + }); + } else { + //both TCP and UDP. Finish discovery after both calls returned, ignoring UDP failure + FutureResponse fr1 = peer.pingRPC().pingTCPProbe(peerAddress, cc, DiscoverBuilder.this); + fr1.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if (future.isFailed()) { + LOG.warn("FutureDiscover (2): We need at least the TCP connection {} - {}", + future, futureDiscover.failedReason()); + futureDiscover.failed("FutureDiscover (2): We need at least the TCP connection", future); + } + } + }); + FutureResponse fr2 = peer.pingRPC().pingUDPProbe(peerAddress, cc, DiscoverBuilder.this); + fr2.addListener(new BaseFutureAdapter() { + @Override + public void operationComplete(FutureResponse future) throws Exception { + if (future.isFailed()) { + LOG.warn("FutureDiscover (2): UDP failed connection {} - {}", + future, futureDiscover.failedReason()); + } + } + }); + } + } + } diff --git a/core/src/main/java/net/tomp2p/rpc/PingRPC.java b/core/src/main/java/net/tomp2p/rpc/PingRPC.java index 5671dcec1..921ab78bd 100644 --- a/core/src/main/java/net/tomp2p/rpc/PingRPC.java +++ b/core/src/main/java/net/tomp2p/rpc/PingRPC.java @@ -191,8 +191,8 @@ public FutureResponse fireTCP(final PeerAddress remotePeer, final ChannelCreator * @param remotePeer * The destination peer * @param channelCreator - * The channel creator where we create a UPD channel - * @return The future that will be triggered when we receive an answer or something fails. + * The channel creator where we create a UDP channel + * @return The future that will be triggered when we receive an answer or something fails. */ public FutureResponse pingUDPDiscover(final PeerAddress remotePeer, final ChannelCreator channelCreator, final ConnectionConfiguration configuration) {