package org.hive2hive.client.menu;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import net.tomp2p.nat.PeerBuilderNAT;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.relay.RelayType;
import net.tomp2p.relay.android.AndroidRelayServerConfig;
import net.tomp2p.relay.buffer.MessageBufferConfiguration;
import net.tomp2p.relay.tcp.buffered.BufferedTCPRelayServerConfig;
import org.hive2hive.client.ConsoleClient;
import org.hive2hive.client.console.H2HConsoleMenu;
import org.hive2hive.client.console.H2HConsoleMenuItem;
import org.hive2hive.client.util.FileEventListener;
import org.hive2hive.client.util.MenuContainer;
import org.hive2hive.core.H2HConstants;
import org.hive2hive.core.api.H2HNode;
import org.hive2hive.core.api.configs.FileConfiguration;
import org.hive2hive.core.api.configs.NetworkConfiguration;
import org.hive2hive.core.api.interfaces.IFileConfiguration;
import org.hive2hive.core.api.interfaces.IH2HNode;
import org.hive2hive.core.security.BCSecurityClassProvider;
import org.hive2hive.core.security.H2HDefaultEncryption;
import org.hive2hive.core.serializer.FSTSerializer;
import org.hive2hive.core.serializer.IH2HSerialize;
import org.hive2hive.core.serializer.JavaSerializer;
/**
* The network configuration menu of the {@link ConsoleClient}.
*
* @author Christian, Nico
*
*/
public final class NodeMenu extends H2HConsoleMenu {
private H2HConsoleMenuItem createNetworkMenuItem;
private H2HConsoleMenuItem connectToExistingNetworkItem;
private IH2HNode node;
private BigInteger maxFileSize = H2HConstants.DEFAULT_MAX_FILE_SIZE;
private int maxNumOfVersions = H2HConstants.DEFAULT_MAX_NUM_OF_VERSIONS;
private BigInteger maxSizeAllVersions = H2HConstants.DEFAULT_MAX_SIZE_OF_ALL_VERSIONS;
private int chunkSize = H2HConstants.DEFAULT_CHUNK_SIZE;
public NodeMenu(MenuContainer menus) {
super(menus);
}
@Override
protected void createItems() {
createNetworkMenuItem = new H2HConsoleMenuItem("Create New Network") {
protected void execute() {
buildNode();
connectNode(NetworkConfiguration.createInitial(askNodeID()));
}
};
connectToExistingNetworkItem = new H2HConsoleMenuItem("Connect to Existing Network") {
protected void execute() throws UnknownHostException {
String nodeID = askNodeID();
print("Specify Bootstrap Address:");
InetAddress bootstrapAddress = InetAddress.getByName(awaitStringParameter());
String bootstrapPort = "default";
if (isExpertMode) {
print("Specify Bootstrap Port or enter 'default':");
bootstrapPort = awaitStringParameter();
}
buildNode();
NetworkConfiguration config = NetworkConfiguration.create(nodeID, bootstrapAddress);
if (!"default".equalsIgnoreCase(bootstrapPort)) {
config.setBootstrapPort(Integer.parseInt(bootstrapPort));
}
connectNode(config);
}
};
}
@Override
protected void addMenuItems() {
if (isExpertMode) {
add(new H2HConsoleMenuItem("Set MaxFileSize") {
protected void execute() {
print("Specify MaxFileSize:");
maxFileSize = BigInteger.valueOf(awaitIntParameter());
}
});
add(new H2HConsoleMenuItem("Set MaxNumOfVersions") {
protected void execute() {
print("Specify MaxNumOfVersions:");
maxNumOfVersions = awaitIntParameter();
}
});
add(new H2HConsoleMenuItem("Set MaxSizeAllVersions") {
protected void execute() {
print("Specify MaxSizeAllVersions:");
maxSizeAllVersions = BigInteger.valueOf(awaitIntParameter());
}
});
add(new H2HConsoleMenuItem("Set ChunkSize") {
protected void execute() {
print("Specify ChunkSize:");
chunkSize = awaitIntParameter();
}
});
add(new H2HConsoleMenuItem("Open Utils") {
protected void execute() {
new UtilMenu().open();
}
});
}
add(createNetworkMenuItem);
add(connectToExistingNetworkItem);
}
@Override
public String getInstruction() {
if (isExpertMode) {
return "Configure and set up your own network or connect to an existing one.";
} else {
return "Do you want to create a new network or connect to an existing one?";
}
}
public IH2HNode getNode() {
return node;
}
public boolean createNetwork() {
if (getNode() == null) {
H2HConsoleMenuItem.printPrecondition("You are not connected to a network. Connect to a network first.");
open();
}
return getNode() != null;
}
private void buildNode() {
IFileConfiguration fileConfig = FileConfiguration.createCustom(maxFileSize, maxNumOfVersions, maxSizeAllVersions,
chunkSize);
IH2HSerialize serializer;
if ("java".equalsIgnoreCase(config.getString("Serializer.mode"))) {
serializer = new JavaSerializer();
} else {
serializer = new FSTSerializer(config.getBoolean("Serializer.FST.unsafe"), new BCSecurityClassProvider());
}
node = H2HNode.createNode(fileConfig, new H2HDefaultEncryption(serializer), serializer);
}
private void connectNode(NetworkConfiguration networkConfig) {
String bindPort = "auto";
if (isExpertMode) {
print("Specify Port to bind this new peer or enter 'auto':");
bindPort = awaitStringParameter();
}
if (!"auto".equalsIgnoreCase(bindPort)) {
networkConfig.setPort(Integer.parseInt(bindPort));
}
if (node.connect(networkConfig)) {
print("Network connection successfully established.");
// connect the event bus
node.getFileManager().subscribeFileEvents(new FileEventListener(node.getFileManager()));
String address = config.getString("InetAddress");
if (!"auto".equalsIgnoreCase(address)) {
try {
InetAddress inetAddress = InetAddress.getByName(address);
print("Binding to address " + inetAddress);
PeerAddress peerAddress = node.getPeer().peerBean().serverPeerAddress().changeAddress(inetAddress);
node.getPeer().peerBean().serverPeerAddress(peerAddress);
} catch (UnknownHostException e) {
print("Cannot resolve address " + address);
}
}
if (config.getBoolean("Relay.enabled")) {
print("Starting relay functionality");
String authenticationKey = config.getString("Relay.GCM.api-key");
long bufferAge = config.getDuration("Relay.GCM.buffer-age-limit", TimeUnit.MILLISECONDS);
MessageBufferConfiguration bufferConfiguration = new MessageBufferConfiguration().bufferAgeLimit(bufferAge);
AndroidRelayServerConfig androidServer = new AndroidRelayServerConfig(authenticationKey, 5,
bufferConfiguration);
BufferedTCPRelayServerConfig tcpServer = new BufferedTCPRelayServerConfig(bufferConfiguration);
new PeerBuilderNAT(node.getPeer().peer()).addRelayServerConfiguration(RelayType.ANDROID, androidServer)
.addRelayServerConfiguration(RelayType.BUFFERED_OPENTCP, tcpServer).start();
}
exit();
} else {
print("Network connection could not be established.");
}
}
private String askNodeID() {
String nodeID = UUID.randomUUID().toString();
if (isExpertMode) {
print("Specify Node ID:");
nodeID = awaitStringParameter();
}
return nodeID;
}
}