diff --git a/app/build.gradle b/app/build.gradle index 9e4d154..68be1b8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -58,6 +58,11 @@ dependencies { implementation 'com.esotericsoftware:kryo:5.0.0-RC1' implementation 'com.github.instacart.truetime-android:library:3.4' + + implementation 'jdom:jdom:1.1' + implementation 'commons-beanutils:commons-beanutils:1.8.3' + implementation 'org.apache.tomcat:servlet-api:6.0.35' + //implementation group: 'org.eclipse.jetty.orbit', name: 'javax.servlet.jsp', version: '2.2.0.v201112011158' } repositories { mavenCentral() diff --git a/app/libs/FreePastry-2.1.jar b/app/libs/FreePastry-2.1.jar index 226a779..c53a698 100644 Binary files a/app/libs/FreePastry-2.1.jar and b/app/libs/FreePastry-2.1.jar differ diff --git a/app/libs/android-jxpath-1.0-Alpha3-SNAPSHOT.jar b/app/libs/android-jxpath-1.0-Alpha3-SNAPSHOT.jar new file mode 100644 index 0000000..be8b271 Binary files /dev/null and b/app/libs/android-jxpath-1.0-Alpha3-SNAPSHOT.jar differ diff --git a/app/libs/openbeans-1.0.jar b/app/libs/openbeans-1.0.jar new file mode 100644 index 0000000..7e61907 Binary files /dev/null and b/app/libs/openbeans-1.0.jar differ diff --git a/app/libs/sbbi-upnplib-1.0.4.jar b/app/libs/sbbi-upnplib-1.0.4.jar new file mode 100644 index 0000000..d26e132 Binary files /dev/null and b/app/libs/sbbi-upnplib-1.0.4.jar differ diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java b/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java index b6d5224..22026fc 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/NetworkHandler.java @@ -75,4 +75,45 @@ public class NetworkHandler implements INetworkObserver { } } } + + public static void handleNewChat(String chatID) { + Data newChat = P2PUtils.get(AppHelper.getPeerID() + "_pendingChats", chatID); + if (newChat != null) { + NewChatRequestMessage newChatRequestMessage = null; + try { + newChatRequestMessage = gson.fromJson((String) newChat.object(), NewChatRequestMessage.class); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + ChatMember chatMember = new ChatMember(AppHelper.getPeerID(), AppHelper.getPeerID()); + Data putData = null; + try { + putData = new Data(gson.toJson(chatMember)).protectEntry(keyPairManager.openMainKeyPair()); + } catch (IOException e) { + e.printStackTrace(); + } + + P2PUtils.put(newChatRequestMessage.getChatID() + "_members", AppHelper.getPeerID(), putData); + + LocalDBWrapper.createChatEntry( + newChatRequestMessage.getChatID(), + newChatRequestMessage.getUsername(), + newChatRequestMessage.getChatID() + "_metadata", + newChatRequestMessage.getChatID() + "_members", + newChatRequestMessage.getChunkID() + ); + + P2PUtils.remove(AppHelper.getPeerID() + "_pendingChats", newChatRequestMessage.getChatID()); + String messageID = UUID.randomUUID().toString(); + try { + P2PUtils.put(newChatRequestMessage.getChatID() + "_messages", messageID, new Data(gson.toJson(new JoinChatMessage(AppHelper.getPeerID(), AppHelper.getUsername() == null ? AppHelper.getPeerID() : AppHelper.getUsername(), newChatRequestMessage.getChatID(), System.currentTimeMillis()))).protectEntry(keyPairManager.openMainKeyPair())); + } catch (IOException e) { + e.printStackTrace(); + } + ObservableUtils.notifyUI(UIActions.SUCCESSFUL_CREATE_CHAT); + } + } } \ No newline at end of file diff --git a/app/src/main/java/io/github/chronosx88/influence/helpers/P2PUtils.java b/app/src/main/java/io/github/chronosx88/influence/helpers/P2PUtils.java index 0d914e1..c8b9d38 100644 --- a/app/src/main/java/io/github/chronosx88/influence/helpers/P2PUtils.java +++ b/app/src/main/java/io/github/chronosx88/influence/helpers/P2PUtils.java @@ -53,6 +53,20 @@ public class P2PUtils { return null; } + public static Data get(String locationKey, String contentKey) { + FutureGet futureGet = peerDHT + .get(Number160.createHash(locationKey)) + .contentKey(Number160.createHash(contentKey)) + .start() + .awaitUninterruptibly(); + if(futureGet != null) { + if(!futureGet.isEmpty()) { + return futureGet.data(); + } + } + return null; + } + public static boolean remove(String locationKey, String contentKey) { FutureRemove futureRemove = peerDHT .remove(Number160.createHash(locationKey)) diff --git a/app/src/main/java/io/github/chronosx88/influence/logic/MainLogic.java b/app/src/main/java/io/github/chronosx88/influence/logic/MainLogic.java index 8f67b52..547ed84 100644 --- a/app/src/main/java/io/github/chronosx88/influence/logic/MainLogic.java +++ b/app/src/main/java/io/github/chronosx88/influence/logic/MainLogic.java @@ -7,10 +7,8 @@ import android.util.Log; import com.google.gson.Gson; import com.google.gson.JsonObject; -import net.tomp2p.connection.Bindings; import net.tomp2p.connection.ChannelClientConfiguration; import net.tomp2p.connection.ChannelServerConfiguration; -import net.tomp2p.connection.Ports; import net.tomp2p.connection.RSASignatureFactory; import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; @@ -39,8 +37,6 @@ import java.net.UnknownHostException; import java.security.KeyPair; import java.util.ArrayList; import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; import java.util.UUID; import io.github.chronosx88.influence.contracts.CoreContracts; @@ -56,11 +52,9 @@ import io.github.chronosx88.influence.helpers.actions.UIActions; import io.github.chronosx88.influence.models.ChatMetadata; import io.github.chronosx88.influence.models.NewChatRequestMessage; import io.github.chronosx88.influence.models.PublicUserProfile; -import io.github.chronosx88.influence.notificationSystem.NotificationHandler; +import io.github.chronosx88.influence.models.notifications.NewChatNotification; import io.github.chronosx88.influence.notificationSystem.NotificationSystem; import rice.environment.Environment; -import rice.p2p.scribe.ScribeContent; -import rice.pastry.NodeHandle; import rice.pastry.NodeIdFactory; import rice.pastry.PastryNode; import rice.pastry.socket.internet.InternetPastryNodeFactory; @@ -188,7 +182,11 @@ public class MainLogic implements CoreContracts.IMainLogicContract { publicProfileToDHT(); SettingsLogic.Companion.publishUsername(AppHelper.getUsername(), AppHelper.getUsername()); NetworkHandler.handlePendingChatRequests(); - AppHelper.getNotificationSystem().subscribe(AppHelper.getPeerID() + "_newChats", notification -> NetworkHandler.handlePendingChatRequests()); + AppHelper.getNotificationSystem().subscribe(AppHelper.getPeerID() + "_newChats", notification -> { + if(notification instanceof NewChatNotification) { + NetworkHandler.handleNewChat(((NewChatNotification) notification).getChatID()); + } + }); /*TimerTask timerTask = new TimerTask() { @Override public void run() { @@ -263,7 +261,9 @@ public class MainLogic implements CoreContracts.IMainLogicContract { peerDHT.peer().announceShutdown().start().awaitUninterruptibly(); peerDHT.peer().shutdown().awaitUninterruptibly(); } - storage.close(); + if(storage != null) { + storage.close(); + } System.exit(0); }).start(); } @@ -321,7 +321,7 @@ public class MainLogic implements CoreContracts.IMainLogicContract { return; } - NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getUsername(), System.currentTimeMillis(), 0); + NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getUsername() == null ? AppHelper.getPeerID() : AppHelper.getUsername(), System.currentTimeMillis(), 0); try { if(P2PUtils.put(companionPeerID + "_pendingChats", newChatRequestMessage.getChatID(), new Data(gson.toJson(newChatRequestMessage)))) { Log.i(LOG_TAG, "# Create new offline chat request is successful! ChatID: " + newChatRequestMessage.getChatID()); @@ -344,6 +344,7 @@ public class MainLogic implements CoreContracts.IMainLogicContract { P2PUtils.put(newChatRequestMessage.getChatID() + "_metadata", null, data); LocalDBWrapper.createChatEntry(newChatRequestMessage.getChatID(), username, newChatRequestMessage.getChatID() + "_metadata", newChatRequestMessage.getChatID() + "_members", 0); ObservableUtils.notifyUI(UIActions.NEW_CHAT); + AppHelper.getNotificationSystem().publish(companionPeerID + "_newChats", new NewChatNotification(newChatRequestMessage.getChatID())); } private PublicUserProfile getPublicProfile(String peerID) { @@ -376,20 +377,18 @@ public class MainLogic implements CoreContracts.IMainLogicContract { private boolean createPastryNode(int bindPort, InetSocketAddress bootAddress) throws Exception { Environment env = new Environment(); env.getParameters().setString("probe_for_external_address","true"); + env.getParameters().setString("nat_search_policy", "never"); AppHelper.storePastryEnvironment(env); NodeIdFactory nidFactory = new RandomNodeIdFactory(env); InternetPastryNodeFactory factory = new InternetPastryNodeFactory(nidFactory, bindPort, env); - NodeHandle bootHandle = factory.getNodeHandle(bootAddress); - PastryNode node; - if(bootHandle != null) { - node = factory.newNode(bootHandle); - } else { - return false; - } + PastryNode node = factory.newNode(); + + node.boot(bootAddress); + // the node may require sending several messages to fully boot into the ring synchronized(node) { while(!node.isReady() && !node.joinFailed()) { - node.wait(100); + node.wait(500); if (node.joinFailed()) { return false; } diff --git a/app/src/main/java/io/github/chronosx88/influence/models/notifications/NewChatNotification.java b/app/src/main/java/io/github/chronosx88/influence/models/notifications/NewChatNotification.java new file mode 100644 index 0000000..4eb7694 --- /dev/null +++ b/app/src/main/java/io/github/chronosx88/influence/models/notifications/NewChatNotification.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 ChronosX88 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github.chronosx88.influence.models.notifications; + +import rice.p2p.scribe.ScribeContent; + +public class NewChatNotification implements ScribeContent { + private String chatID; + + public NewChatNotification(String chatID) { + this.chatID = chatID; + } + + public String getChatID() { + return chatID; + } + + public void setChatID(String chatID) { + this.chatID = chatID; + } +}