updated to master branch of tomp2p. refactored messaging. bootstrapping to seed node (server supported). right management.

This commit is contained in:
Manfred Karrer 2014-07-31 18:45:58 +02:00
parent 222045ca5a
commit 57d5ddcc4f
54 changed files with 3284 additions and 717 deletions

View file

@ -0,0 +1,18 @@
package io.bitsquare;
import io.bitsquare.btc.BtcValidatorTest;
import io.bitsquare.gui.util.BitSquareConverterTest;
import io.bitsquare.gui.util.BitSquareValidatorTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
BtcValidatorTest.class,
BitSquareConverterTest.class,
BitSquareValidatorTest.class,
})
public class BitSquareTestSuite
{
}

View file

@ -0,0 +1,34 @@
package io.bitsquare.btc;
import com.google.bitcoin.core.Transaction;
import java.math.BigInteger;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class BtcValidatorTest
{
@Test
public void testIsMinSpendableAmount()
{
BigInteger amount = null;
//noinspection ConstantConditions
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
amount = BigInteger.ZERO;
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
amount = FeePolicy.TX_FEE;
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
amount = Transaction.MIN_NONDUST_OUTPUT;
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT);
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE);
assertTrue("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
}
}

View file

@ -0,0 +1,29 @@
package io.bitsquare.gui.util;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class BitSquareConverterTest
{
@Test
public void testStringToDouble()
{
assertEquals(1, BitSquareConverter.stringToDouble("1"), 0);
assertEquals(0.1, BitSquareConverter.stringToDouble("0.1"), 0);
assertEquals(0.1, BitSquareConverter.stringToDouble("0,1"), 0);
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(null), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("."), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(","), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("a"), 0);
}
}

View file

@ -0,0 +1,38 @@
package io.bitsquare.gui.util;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class BitSquareValidatorTest
{
@Test
public void testValidateStringAsDouble()
{
assertTrue(BitSquareValidator.validateStringAsDouble("0"));
assertTrue(BitSquareValidator.validateStringAsDouble("1"));
assertTrue(BitSquareValidator.validateStringAsDouble("0,1"));
assertTrue(BitSquareValidator.validateStringAsDouble("0.01"));
assertFalse(BitSquareValidator.validateStringAsDouble(""));
assertFalse(BitSquareValidator.validateStringAsDouble("a"));
assertFalse(BitSquareValidator.validateStringAsDouble("0.0.1"));
assertFalse(BitSquareValidator.validateStringAsDouble("1,000.1"));
assertFalse(BitSquareValidator.validateStringAsDouble("1.000,1"));
assertFalse(BitSquareValidator.validateStringAsDouble(null));
}
@Test
public void testValidateStringNotEmpty()
{
assertTrue(BitSquareValidator.validateStringNotEmpty("a"));
assertTrue(BitSquareValidator.validateStringNotEmpty("123"));
assertFalse(BitSquareValidator.validateStringNotEmpty(""));
assertFalse(BitSquareValidator.validateStringNotEmpty(" "));
assertFalse(BitSquareValidator.validateStringNotEmpty(null));
}
}

View file

@ -0,0 +1,375 @@
package io.bitsquare.msg;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Random;
import net.tomp2p.dht.FutureGet;
import net.tomp2p.dht.FuturePut;
import net.tomp2p.dht.FutureRemove;
import net.tomp2p.dht.PeerDHT;
import net.tomp2p.futures.FutureDirect;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.rpc.ObjectDataReply;
import net.tomp2p.storage.Data;
import net.tomp2p.utils.Utils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.*;
public class P2PNodeTest
{
private static final Logger log = LoggerFactory.getLogger(P2PNodeTest.class);
final private static Random rnd = new Random(42L);
@Test
public void testSendData() throws Exception
{
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
PeerDHT master = peers[0];
PeerDHT client = peers[1];
PeerDHT otherPeer = peers[2];
UtilsDHT2.perfectRouting(peers);
for (final PeerDHT peer : peers)
{
peer.peer().objectDataReply(new ObjectDataReply()
{
@Override
public Object reply(PeerAddress sender, Object request) throws Exception
{
return true;
}
});
}
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024);
KeyPair keyPairClient = keyGen.genKeyPair();
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
P2PNode node;
Number160 locationKey;
Object object;
FutureDirect futureDirect;
node = new P2PNode(keyPairClient, client);
object = "clients data";
futureDirect = node.sendData(otherPeer.peerAddress(), object);
futureDirect.awaitUninterruptibly();
assertTrue(futureDirect.isSuccess());
// we return true from objectDataReply
assertTrue((Boolean) futureDirect.object());
}
@Test
public void testProtectedPutGet() throws Exception
{
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
PeerDHT master = peers[0];
PeerDHT client = peers[1];
PeerDHT otherPeer = peers[2];
UtilsDHT2.perfectRouting(peers);
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024);
KeyPair keyPairClient = keyGen.genKeyPair();
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
P2PNode node;
Number160 locationKey;
Data data;
FuturePut futurePut;
FutureGet futureGet;
// otherPeer tries to squat clients location store
// he can do it but as he has not the domain key of the client he cannot do any harm
// he only can store und that path: locationKey.otherPeerDomainKey.data
node = new P2PNode(keyPairOtherPeer, otherPeer);
locationKey = Number160.createHash("clients location");
data = new Data("otherPeer data");
futurePut = node.putDomainProtectedData(locationKey, data);
futurePut.awaitUninterruptibly();
assertTrue(futurePut.isSuccess());
futureGet = node.getDomainProtectedData(locationKey, keyPairOtherPeer.getPublic());
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
assertEquals("otherPeer data", futureGet.data().object());
// client store his data und his domainkey, no problem with previous occupied
// he only can store und that path: locationKey.clientDomainKey.data
node = new P2PNode(keyPairClient, client);
locationKey = Number160.createHash("clients location");
data = new Data("client data");
futurePut = node.putDomainProtectedData(locationKey, data);
futurePut.awaitUninterruptibly();
assertTrue(futurePut.isSuccess());
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
assertEquals("client data", futureGet.data().object());
// also other peers can read that data if they know the public key of the client
node = new P2PNode(keyPairOtherPeer, otherPeer);
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
assertEquals("client data", futureGet.data().object());
// other peer try to use pub key of other peer as domain key hash.
// must fail as he don't have the full key pair (private key of client missing)
locationKey = Number160.createHash("clients location");
data = new Data("otherPeer data hack");
data.protectEntry(keyPairOtherPeer);
// he use the pub key from the client
final Number160 keyHash = Utils.makeSHAHash(keyPairClient.getPublic().getEncoded());
futurePut = otherPeer.put(locationKey).data(data).keyPair(keyPairOtherPeer).domainKey(keyHash).protectDomain().start();
futurePut.awaitUninterruptibly();
assertFalse(futurePut.isSuccess());
// he can read his prev. stored data
node = new P2PNode(keyPairOtherPeer, otherPeer);
futureGet = node.getDomainProtectedData(locationKey, keyPairOtherPeer.getPublic());
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
assertEquals("otherPeer data", futureGet.data().object());
// he can read clients data
futureGet = node.getDomainProtectedData(locationKey, keyPairClient.getPublic());
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
assertEquals("client data", futureGet.data().object());
master.shutdown();
}
@Test
public void testAddToListGetList() throws Exception
{
PeerDHT[] peers = UtilsDHT2.createNodes(3, rnd, 41001);
PeerDHT master = peers[0];
PeerDHT client = peers[1];
PeerDHT otherPeer = peers[2];
UtilsDHT2.perfectRouting(peers);
P2PNode node;
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024);
KeyPair keyPairClient = keyGen.genKeyPair();
KeyPair keyPairOtherPeer = keyGen.genKeyPair();
Number160 locationKey;
Data data;
FuturePut futurePut;
FutureGet futureGet;
// client add a value
node = new P2PNode(keyPairClient, client);
locationKey = Number160.createHash("add to list clients location");
data = new Data("add to list client data1");
Data data_1 = data;
futurePut = node.addProtectedData(locationKey, data);
futurePut.awaitUninterruptibly();
assertTrue(futurePut.isSuccess());
data = new Data("add to list client data2");
Data data_2 = data;
futurePut = node.addProtectedData(locationKey, data);
futurePut.awaitUninterruptibly();
assertTrue(futurePut.isSuccess());
futureGet = node.getDataMap(locationKey);
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
boolean foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data1");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
boolean foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data2");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
assertTrue(foundData1);
assertTrue(foundData2);
assertEquals(2, futureGet.dataMap().values().size());
// other peer tried to overwrite that entry
// but will not succeed, instead he will add a new entry.
// TODO investigate why it is not possible to overwrite the entry with that method
// The protection entry with the key does not make any difference as also the client himself cannot overwrite any entry
// http://tomp2p.net/doc/P2P-with-TomP2P-1.pdf
// "add(location_key, value) is translated to put(location_key, hash(value), value)"
// fake content key with content key from previous clients entry
Number160 contentKey = Number160.createHash("add to list client data1");
data = new Data("add to list other peer data HACK!");
data.protectEntry(keyPairOtherPeer); // also with client key it does not work...
futurePut = otherPeer.put(locationKey).data(contentKey, data).keyPair(keyPairOtherPeer).start();
futurePut.awaitUninterruptibly();
assertTrue(futurePut.isSuccess());
node = new P2PNode(keyPairOtherPeer, otherPeer);
futureGet = node.getDataMap(locationKey);
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data1");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data2");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
boolean foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list other peer data HACK!");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
assertTrue(foundData1);
assertTrue(foundData2);
assertTrue(foundData3);
assertEquals(3, futureGet.dataMap().values().size());
// client removes his entry -> OK
node = new P2PNode(keyPairClient, client);
FutureRemove futureRemove = node.removeFromDataMap(locationKey, data_1);
futureRemove.awaitUninterruptibly();
assertTrue(futureRemove.isSuccess());
futureGet = node.getDataMap(locationKey);
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data1");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data2");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list other peer data HACK!");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
assertFalse(foundData1);
assertTrue(foundData2);
assertTrue(foundData3);
assertEquals(2, futureGet.dataMap().values().size());
// otherPeer tries to removes client entry -> FAIL
node = new P2PNode(keyPairOtherPeer, otherPeer);
futureRemove = node.removeFromDataMap(locationKey, data_2);
futureRemove.awaitUninterruptibly();
assertFalse(futureRemove.isSuccess());
futureGet = node.getDataMap(locationKey);
futureGet.awaitUninterruptibly();
assertTrue(futureGet.isSuccess());
foundData1 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data1");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
foundData2 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list client data2");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
foundData3 = futureGet.dataMap().values().stream().anyMatch(data1 -> {
try
{
return data1.object().equals("add to list other peer data HACK!");
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
return false;
});
assertFalse(foundData1);
assertTrue(foundData2);
assertTrue(foundData3);
assertEquals(2, futureGet.dataMap().values().size());
master.shutdown();
}
}

View file

@ -0,0 +1,412 @@
/*
* 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 io.bitsquare.msg;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import net.tomp2p.connection.Bindings;
import net.tomp2p.dht.PeerBuilderDHT;
import net.tomp2p.dht.PeerDHT;
import net.tomp2p.futures.FutureBootstrap;
import net.tomp2p.futures.FutureDiscover;
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.*;
public class UtilsDHT2
{
/**
* Used to make the testcases predictable. Used as an input for {@link java.util.Random}.
*/
public static final long THE_ANSWER = 42L;
/**
* Having two peers in a network, the seed needs to be different, otherwise we create a peer with the same id twice.
*/
public static final long THE_ANSWER2 = 43L;
public static Message createDummyMessage() throws UnknownHostException
{
return createDummyMessage(false, false);
}
public static Message createDummyMessage(boolean firewallUDP, boolean firewallTCP)
throws UnknownHostException
{
return createDummyMessage(new Number160("0x4321"), "127.0.0.1", 8001, 8002, new Number160("0x1234"),
"127.0.0.1", 8003, 8004, (byte) 0, Type.REQUEST_1, firewallUDP, firewallTCP);
}
public static PeerAddress createAddress(Number160 id) throws UnknownHostException
{
return createAddress(id, "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress() throws UnknownHostException
{
return createAddress(new Number160("0x5678"), "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress(int id) throws UnknownHostException
{
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
}
public static PeerAddress createAddress(String id) throws UnknownHostException
{
return createAddress(new Number160(id), "127.0.0.1", 8005, 8006, false, false);
}
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, firewallTCP, firewallUDP, false,
PeerAddress.EMPTY_PEER_SOCKET_ADDRESSES);
return n1;
}
public static Message createDummyMessage(Number160 idSender, String inetSender, int tcpPortSendor,
int udpPortSender, Number160 idRecipien, String inetRecipient, int tcpPortRecipient,
int udpPortRecipient, byte command, Type type, boolean firewallUDP, boolean firewallTCP)
throws UnknownHostException
{
Message message = new Message();
PeerAddress n1 = createAddress(idSender, inetSender, tcpPortSendor, udpPortSender, firewallUDP,
firewallTCP);
message.sender(n1);
//
PeerAddress n2 = createAddress(idRecipien, inetRecipient, tcpPortRecipient, udpPortRecipient,
firewallUDP, firewallTCP);
message.recipient(n2);
message.type(type);
message.command(command);
return message;
}
public static PeerDHT[] createNodes(int nrOfPeers, Random rnd, int port) throws Exception
{
return createNodes(nrOfPeers, rnd, port, null);
}
public static PeerDHT[] 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 PeerDHT[] 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();
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)
.externalBindings(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).externalBindings(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).externalBindings(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)
.externalBindings(bindings).peerMap(peerMap).masterPeer(master)
.start();
peers[i] = new PeerBuilderDHT(peer).start();
}
}
System.err.println("peers created.");
return peers;
}
public static Peer[] createRealNodes(int nrOfPeers, Random rnd, int startPort,
AutomaticFuture automaticFuture) throws Exception
{
if (nrOfPeers < 1)
{
throw new IllegalArgumentException("Cannot create less than 1 peer");
}
Peer[] peers = new Peer[nrOfPeers];
for (int i = 0; i < nrOfPeers; i++)
{
peers[i] = new PeerBuilder(new Number160(rnd))
.ports(startPort + i).start().addAutomaticFuture(automaticFuture);
}
System.err.println("real peers created.");
return peers;
}
public static Peer[] createNonMaintenanceNodes(int nrOfPeers, Random rnd, int port) throws IOException
{
if (nrOfPeers < 1)
{
throw new IllegalArgumentException("Cannot create less than 1 peer");
}
Peer[] peers = new Peer[nrOfPeers];
peers[0] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).ports(port).start();
for (int i = 1; i < nrOfPeers; i++)
{
peers[i] = new PeerBuilder(new Number160(rnd)).enableMaintenance(false).masterPeer(peers[0])
.start();
}
System.err.println("non-maintenance 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);
}
System.err.println("perfect routing done.");
}
public static void perfectRoutingIndirect(PeerDHT... 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(), peers[j].peerAddress());
}
System.err.println("perfect routing done.");
}
public static void main(String[] args) throws IOException
{
createTempDirectory();
}
private static final int TEMP_DIR_ATTEMPTS = 10000;
public static File createTempDirectory() throws IOException
{
File baseDir = new File(System.getProperty("java.io.tmpdir"));
String baseName = System.currentTimeMillis() + "-";
for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++)
{
File tempDir = new File(baseDir, baseName + counter);
if (tempDir.mkdir())
{
return tempDir;
}
}
throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS
+ " attempts (tried " + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}
public static Peer[] createAndAttachNodes(int nr, int port, Random rnd) throws Exception
{
Peer[] peers = new Peer[nr];
for (int i = 0; i < nr; i++)
{
if (i == 0)
{
peers[0] = new PeerBuilder(new Number160(rnd)).ports(port).start();
}
else
{
peers[i] = new PeerBuilder(new Number160(rnd)).masterPeer(peers[0]).start();
}
}
return peers;
}
public static void bootstrap(Peer[] peers)
{
List<FutureBootstrap> futures1 = new ArrayList<FutureBootstrap>();
List<FutureDiscover> futures2 = new ArrayList<FutureDiscover>();
for (int i = 1; i < peers.length; i++)
{
FutureDiscover tmp = peers[i].discover().peerAddress(peers[0].peerAddress()).start();
futures2.add(tmp);
}
for (FutureDiscover future : futures2)
{
future.awaitUninterruptibly();
}
for (int i = 1; i < peers.length; i++)
{
FutureBootstrap tmp = peers[i].bootstrap().peerAddress(peers[0].peerAddress()).start();
futures1.add(tmp);
}
for (int i = 1; i < peers.length; i++)
{
FutureBootstrap tmp = peers[0].bootstrap().peerAddress(peers[i].peerAddress()).start();
futures1.add(tmp);
}
for (FutureBootstrap future : futures1)
future.awaitUninterruptibly();
}
public static void routing(Number160 key, Peer[] peers, int start)
{
System.out.println("routing: searching for key " + key);
NavigableSet<PeerAddress> pa1 = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
NavigableSet<PeerAddress> queried = new TreeSet<PeerAddress>(PeerMap.createComparator(key));
Number160 result = Number160.ZERO;
Number160 resultPeer = new Number160("0xd75d1a3d57841fbc9e2a3d175d6a35dc2e15b9f");
int round = 0;
while (!resultPeer.equals(result))
{
System.out.println("round " + round);
round++;
pa1.addAll(peers[start].peerBean().peerMap().all());
queried.add(peers[start].peerAddress());
System.out.println("closest so far: " + queried.first());
PeerAddress next = pa1.pollFirst();
while (queried.contains(next))
{
next = pa1.pollFirst();
}
result = next.peerId();
start = findNr(next.peerId().toString(), peers);
}
}
public static void findInMap(PeerAddress key, Peer[] peers)
{
for (int i = 0; i < peers.length; i++)
{
if (peers[i].peerBean().peerMap().contains(key))
{
System.out.println("Peer " + i + " with the id " + peers[i].peerID() + " knows the peer "
+ key);
}
}
}
public static int findNr(String string, Peer[] peers)
{
for (int i = 0; i < peers.length; i++)
{
if (peers[i].peerID().equals(new Number160(string)))
{
System.out.println("we found the number " + i + " for peer with id " + string);
return i;
}
}
return -1;
}
public static Peer find(String string, Peer[] peers)
{
for (int i = 0; i < peers.length; i++)
{
if (peers[i].peerID().equals(new Number160(string)))
{
System.out.println("!!we found the number " + i + " for peer with id " + string);
return peers[i];
}
}
return null;
}
public static void exec(String cmd) throws Exception
{
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null)
{
System.out.println(line);
}
br.close();
}
public static PeerAddress createAddressIP(String inet) throws UnknownHostException
{
return createAddress(Number160.createHash(inet), inet, 8005, 8006, false, false);
}
public static PeerAddress[] createDummyAddress(int size, int portTCP, int portUDP) throws UnknownHostException
{
PeerAddress[] pa = new PeerAddress[size];
for (int i = 0; i < size; i++)
{
pa[i] = createAddress(i + 1, portTCP, portUDP);
}
return pa;
}
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);
}
}

View file

@ -0,0 +1,26 @@
package lighthouse.threading;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ConcatenatingListTest
{
@Test
public void basic() throws Exception
{
ObservableList<String> a = FXCollections.observableArrayList();
ObservableList<String> b = FXCollections.observableArrayList();
ConcatenatingList<String> concat = new ConcatenatingList<>(a, b);
assertEquals(0, concat.size());
a.add("1");
assertEquals(1, concat.size());
assertEquals("1", concat.get(0));
b.add("2");
assertEquals(2, concat.size());
assertEquals("2", concat.get(1));
}
}

View file

@ -0,0 +1,91 @@
package lighthouse.threading;
import java.util.LinkedList;
import java.util.Queue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class MappedListTest
{
private ObservableList<String> inputs;
private ObservableList<String> outputs;
private Queue<ListChangeListener.Change<? extends String>> changes;
@Before
public void setup()
{
inputs = FXCollections.observableArrayList();
outputs = new MappedList<>(inputs, str -> "Hello " + str);
changes = new LinkedList<>();
outputs.addListener(changes::add);
}
@Test
public void add() throws Exception
{
assertEquals(0, outputs.size());
inputs.add("Mike");
ListChangeListener.Change<? extends String> change = getChange();
assertTrue(change.wasAdded());
assertEquals("Hello Mike", change.getAddedSubList().get(0));
assertEquals(1, outputs.size());
assertEquals("Hello Mike", outputs.get(0));
inputs.remove(0);
assertEquals(0, outputs.size());
}
private ListChangeListener.Change<? extends String> getChange()
{
ListChangeListener.Change<? extends String> change = changes.poll();
change.next();
return change;
}
@Test
public void remove()
{
inputs.add("Mike");
inputs.add("Dave");
inputs.add("Katniss");
getChange();
getChange();
getChange();
assertEquals("Hello Mike", outputs.get(0));
assertEquals("Hello Dave", outputs.get(1));
assertEquals("Hello Katniss", outputs.get(2));
inputs.remove(0);
ListChangeListener.Change<? extends String> change = getChange();
assertTrue(change.wasRemoved());
assertEquals(2, outputs.size());
assertEquals(1, change.getRemovedSize());
assertEquals("Hello Mike", change.getRemoved().get(0));
assertEquals("Hello Dave", outputs.get(0));
inputs.remove(1);
assertEquals(1, outputs.size());
assertEquals("Hello Dave", outputs.get(0));
}
@Test
public void replace() throws Exception
{
inputs.add("Mike");
inputs.add("Dave");
getChange();
getChange();
inputs.set(0, "Bob");
assertEquals("Hello Bob", outputs.get(0));
ListChangeListener.Change<? extends String> change = getChange();
assertTrue(change.wasReplaced());
assertEquals("Hello Mike", change.getRemoved().get(0));
assertEquals("Hello Bob", change.getAddedSubList().get(0));
}
// Could also test permutation here if I could figure out how to actually apply one!
}