From 127bccd272fc45ac0c06af3b30777c34dbae7290 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 15 Mar 2019 21:23:48 +0400 Subject: [PATCH] Now connecting sna bootstrapping behind NAT --- .../influence/helpers/MessageActions.java | 2 + .../influence/models/MainModel.java | 109 +++++++++++------- .../influence/views/MainActivity.java | 15 ++- 3 files changed, 82 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/MessageActions.java b/app/src/main/java/io/github/chronosx88/influence/helpers/MessageActions.java index ab68f13..636d9fd 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/MessageActions.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/MessageActions.java @@ -5,4 +5,6 @@ public class MessageActions { public static final int NETWORK_ERROR = 0x1; public static final int BOOTSTRAP_SUCCESS = 0x2; public static final int PORT_FORWARDING_ERROR = 0x3; + public static final int RELAY_CONNECTION_ERROR = 0x4; + public static final int BOOTSTRAP_ERROR = 0x5; } diff --git a/app/src/main/java/io/github/chronosx88/influence/models/MainModel.java b/app/src/main/java/io/github/chronosx88/influence/models/MainModel.java index da0847f..712b554 100644 --- a/app/src/main/java/io/github/chronosx88/influence/models/MainModel.java +++ b/app/src/main/java/io/github/chronosx88/influence/models/MainModel.java @@ -14,6 +14,7 @@ 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.relay.tcp.TCPRelayClientConfig; import org.json.JSONException; @@ -23,6 +24,8 @@ import java.io.IOException; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; import java.util.UUID; import io.github.chronosx88.influence.contracts.MainModelContract; @@ -31,10 +34,14 @@ import io.github.chronosx88.influence.helpers.MessageActions; import io.github.chronosx88.influence.helpers.StorageMVStore; public class MainModel implements MainModelContract { + private static final String LOG_TAG = "MainModel"; + private SharedPreferences preferences; private Number160 peerID; private PeerDHT peerDHT; private Context context; + private InetAddress bootstrapAddress = null; + private PeerAddress bootstrapPeerAddress = null; public MainModel() { this.context = AppHelper.getContext(); @@ -56,17 +63,13 @@ public class MainModel implements MainModelContract { new Thread(() -> { try { - InetAddress bootstrapAddress = null; - peerDHT = new PeerBuilderDHT( new PeerBuilder(peerID) .ports(7243) - .behindFirewall() .start() ) .storage(new StorageMVStore(peerID, context.getFilesDir())) .start(); - PeerNAT peerNAT = new PeerBuilderNAT(peerDHT.peer()).start(); try { String bootstrapIP = this.preferences.getString("bootstrapAddress", null); if(bootstrapIP == null) { @@ -93,62 +96,40 @@ public class MainModel implements MainModelContract { } } - FutureDiscover futureDiscover = peerDHT.peer().discover().inetAddress(bootstrapAddress).ports(7243).start(); - FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); - FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT); - futureRelayNAT.awaitUninterruptibly(); - - if(futureDiscover.isSuccess()) { - Log.d("MainModel", "# Success discover! Your IP: " + futureDiscover.peerAddress()); - } else { - Log.d("MainModel", "# Error when discovering: " + futureDiscover.failedReason()); + if(!discoverExternalAddress()) { try { AppHelper.getObservable().notifyObservers(new JSONObject() .put("action", MessageActions.PORT_FORWARDING_ERROR)); - peerDHT.shutdown(); + } catch (JSONException ex) { + ex.printStackTrace(); + } + } + + if(!setupConnectionToRelay()) { + try { + AppHelper.getObservable().notifyObservers(new JSONObject() + .put("action", MessageActions.RELAY_CONNECTION_ERROR)); return; } catch (JSONException ex) { ex.printStackTrace(); } } - if(futureNAT.isSuccess()) { - Log.d("MainModel", "# Success NAT discover! Your IP: " + futureNAT.peerAddress()); - } else { + if(!bootstrapPeer()) { try { - Log.d("MainModel", "# Error when discovering: " + futureNAT.failedReason()); AppHelper.getObservable().notifyObservers(new JSONObject() - .put("action", MessageActions.PORT_FORWARDING_ERROR)); - peerDHT.shutdown(); + .put("action", MessageActions.BOOTSTRAP_ERROR)); return; } catch (JSONException ex) { ex.printStackTrace(); } } - if(futureRelayNAT.isSuccess()) { - Log.d("MainModel", "# Success discover with relay!"); - } else { - try { - Log.d("MainModel", "# Error when discovering: " + futureRelayNAT.failedReason()); - AppHelper.getObservable().notifyObservers(new JSONObject() - .put("action", MessageActions.PORT_FORWARDING_ERROR)); - peerDHT.shutdown(); - return; - } catch (JSONException ex) { - ex.printStackTrace(); - } - } - - FutureBootstrap futureBootstrap = peerDHT.peer().bootstrap().inetAddress(bootstrapAddress).ports(7243).start(); - futureBootstrap.awaitUninterruptibly(); - if(futureBootstrap.isSuccess()) { - try { - AppHelper.getObservable().notifyObservers(new JSONObject() - .put("action", MessageActions.BOOTSTRAP_SUCCESS)); - } catch (JSONException ex) { - ex.printStackTrace(); - } + try { + AppHelper.getObservable().notifyObservers(new JSONObject() + .put("action", MessageActions.BOOTSTRAP_SUCCESS)); + } catch (JSONException ex) { + ex.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); @@ -156,6 +137,48 @@ public class MainModel implements MainModelContract { }).start(); } + private boolean bootstrapPeer() { + FutureBootstrap futureBootstrap = peerDHT.peer().bootstrap().inetAddress(bootstrapAddress).ports(7243).start(); + futureBootstrap.awaitUninterruptibly(); + if(futureBootstrap.isSuccess()) { + Log.i("MainModel", "# Successfully bootstrapped to " + bootstrapAddress.toString()); + return true; + } else { + Log.e("MainModel", "# Cannot bootstrap to " + bootstrapAddress.toString() + ". Reason: " + futureBootstrap.failedReason()); + return false; + } + } + + private boolean discoverExternalAddress() { + FutureDiscover futureDiscover = peerDHT + .peer() + .discover() + .inetAddress(bootstrapAddress) + .ports(7243) + .start(); + futureDiscover.awaitUninterruptibly(); + bootstrapPeerAddress = futureDiscover.reporter(); + if(futureDiscover.isSuccess()) { + Log.i(LOG_TAG, "# Success discover! Your external IP: " + futureDiscover.peerAddress().toString()); + return true; + } else { + Log.e(LOG_TAG, "# Failed to discover my external IP. Reason: " + futureDiscover.failedReason()); + return false; + } + } + + private boolean setupConnectionToRelay() { + PeerNAT peerNat = new PeerBuilderNAT(peerDHT.peer()).start(); + FutureRelayNAT futureRelayNAT = peerNat.startRelay(new TCPRelayClientConfig(), bootstrapPeerAddress).awaitUninterruptibly(); + if (futureRelayNAT.isSuccess()) { + Log.i(LOG_TAG, "# Successfully connected to relay node."); + return true; + } else { + Log.e(LOG_TAG, "# Cannot connect to relay node. Reason: " + futureRelayNAT.failedReason()); + return false; + } + } + @Override public void shutdownPeer() { peerDHT.shutdown(); diff --git a/app/src/main/java/io/github/chronosx88/influence/views/MainActivity.java b/app/src/main/java/io/github/chronosx88/influence/views/MainActivity.java index bef2114..6fd7d59 100644 --- a/app/src/main/java/io/github/chronosx88/influence/views/MainActivity.java +++ b/app/src/main/java/io/github/chronosx88/influence/views/MainActivity.java @@ -114,11 +114,24 @@ public class MainActivity extends AppCompatActivity implements Observer, MainVie } case MessageActions.PORT_FORWARDING_ERROR: { runOnUiThread(() -> { - progressDialog.dismiss(); Toast.makeText(this, "Проблемы с пробросом портов. Возможно, у вас не настроен uPnP.", Toast.LENGTH_LONG).show(); }); break; } + case MessageActions.BOOTSTRAP_ERROR: { + runOnUiThread(() -> { + progressDialog.dismiss(); + Toast.makeText(this, "Не удалось подключиться к бутстрап-ноде.", Toast.LENGTH_LONG).show(); + }); + break; + } + case MessageActions.RELAY_CONNECTION_ERROR: { + runOnUiThread(() -> { + progressDialog.dismiss(); + Toast.makeText(this, "Не удалось подключиться к relay-ноде.", Toast.LENGTH_LONG).show(); + }); + break; + } } } catch (JSONException e) { e.printStackTrace();