diff --git a/build.gradle b/build.gradle index 917a0d4..0e96284 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ subprojects { sourceCompatibility = 1.7 group = 'ch.dissem.jabit' - version = '1.0.2-SNAPSHOT' + version = '1.1.0-SNAPSHOT' ext.isReleaseVersion = !version.endsWith("SNAPSHOT") diff --git a/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.java b/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.java index 51243ab..f33b26c 100644 --- a/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.java +++ b/core/src/main/java/ch/dissem/bitmessage/BitmessageContext.java @@ -17,7 +17,10 @@ package ch.dissem.bitmessage; import ch.dissem.bitmessage.entity.*; -import ch.dissem.bitmessage.entity.payload.*; +import ch.dissem.bitmessage.entity.payload.Broadcast; +import ch.dissem.bitmessage.entity.payload.Msg; +import ch.dissem.bitmessage.entity.payload.ObjectPayload; +import ch.dissem.bitmessage.entity.payload.ObjectType; import ch.dissem.bitmessage.entity.payload.Pubkey.Feature; import ch.dissem.bitmessage.entity.valueobject.Label; import ch.dissem.bitmessage.entity.valueobject.PrivateKey; @@ -65,6 +68,7 @@ public class BitmessageContext { private final InternalContext ctx; + private final Labeler labeler; private final Listener listener; private final NetworkHandler.MessageListener networkListener; @@ -72,8 +76,9 @@ public class BitmessageContext { private BitmessageContext(Builder builder) { ctx = new InternalContext(builder); + labeler = builder.labeler; listener = builder.listener; - networkListener = new DefaultMessageListener(ctx, listener); + networkListener = new DefaultMessageListener(ctx, labeler, listener); // As this thread is used for parts that do POW, which itself uses parallel threads, only // one should be executed at any time. @@ -97,6 +102,10 @@ public class BitmessageContext { return ctx.getMessageRepository(); } + public Labeler labeler() { + return labeler; + } + public BitmessageAddress createIdentity(boolean shorter, Feature... features) { final BitmessageAddress identity = new BitmessageAddress(new PrivateKey( shorter, @@ -280,7 +289,9 @@ public class BitmessageContext { try { Broadcast broadcast = (Broadcast) object.getPayload(); broadcast.decrypt(address); - listener.receive(broadcast.getPlaintext()); + // This decrypts it twice, but on the other hand it doesn't try to decrypt the objects with + // other subscriptions and the interface stays as simple as possible. + networkListener.receive(object); } catch (DecryptionFailedException ignore) { } catch (Exception e) { LOG.debug(e.getMessage(), e); @@ -318,6 +329,7 @@ public class BitmessageContext { Cryptography cryptography; MessageCallback messageCallback; CustomCommandHandler customCommandHandler; + Labeler labeler; Listener listener; int connectionLimit = 150; long connectionTTL = 30 * MINUTE; @@ -378,6 +390,11 @@ public class BitmessageContext { return this; } + public Builder labeler(Labeler labeler) { + this.labeler = labeler; + return this; + } + public Builder listener(Listener listener) { this.listener = listener; return this; @@ -430,6 +447,9 @@ public class BitmessageContext { if (messageCallback == null) { messageCallback = new BaseMessageCallback(); } + if (labeler == null) { + labeler = new DefaultLabeler(); + } if (customCommandHandler == null) { customCommandHandler = new CustomCommandHandler() { @Override diff --git a/core/src/main/java/ch/dissem/bitmessage/DefaultMessageListener.java b/core/src/main/java/ch/dissem/bitmessage/DefaultMessageListener.java index c2c2f64..74a6560 100644 --- a/core/src/main/java/ch/dissem/bitmessage/DefaultMessageListener.java +++ b/core/src/main/java/ch/dissem/bitmessage/DefaultMessageListener.java @@ -20,8 +20,9 @@ import ch.dissem.bitmessage.entity.BitmessageAddress; import ch.dissem.bitmessage.entity.ObjectMessage; import ch.dissem.bitmessage.entity.Plaintext; import ch.dissem.bitmessage.entity.payload.*; -import ch.dissem.bitmessage.entity.valueobject.Label; +import ch.dissem.bitmessage.entity.valueobject.InventoryVector; import ch.dissem.bitmessage.exception.DecryptionFailedException; +import ch.dissem.bitmessage.ports.Labeler; import ch.dissem.bitmessage.ports.NetworkHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,10 +37,12 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY; class DefaultMessageListener implements NetworkHandler.MessageListener { private final static Logger LOG = LoggerFactory.getLogger(DefaultMessageListener.class); private final InternalContext ctx; + private final Labeler labeler; private final BitmessageContext.Listener listener; - public DefaultMessageListener(InternalContext context, BitmessageContext.Listener listener) { + public DefaultMessageListener(InternalContext context, Labeler labeler, BitmessageContext.Listener listener) { this.ctx = context; + this.labeler = labeler; this.listener = listener; } @@ -127,12 +130,7 @@ class DefaultMessageListener implements NetworkHandler.MessageListener { if (!object.isSignatureValid(msg.getPlaintext().getFrom().getPubkey())) { LOG.warn("Msg with IV " + object.getInventoryVector() + " was successfully decrypted, but signature check failed. Ignoring."); } else { - msg.getPlaintext().setStatus(RECEIVED); - msg.getPlaintext().addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.UNREAD)); - msg.getPlaintext().setInventoryVector(object.getInventoryVector()); - ctx.getMessageRepository().save(msg.getPlaintext()); - listener.receive(msg.getPlaintext()); - updatePubkey(msg.getPlaintext().getFrom(), msg.getPlaintext().getFrom().getPubkey()); + receive(object.getInventoryVector(), msg.getPlaintext()); } break; } catch (DecryptionFailedException ignore) { @@ -151,15 +149,19 @@ class DefaultMessageListener implements NetworkHandler.MessageListener { if (!object.isSignatureValid(broadcast.getPlaintext().getFrom().getPubkey())) { LOG.warn("Broadcast with IV " + object.getInventoryVector() + " was successfully decrypted, but signature check failed. Ignoring."); } else { - broadcast.getPlaintext().setStatus(RECEIVED); - broadcast.getPlaintext().addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.BROADCAST, Label.Type.UNREAD)); - broadcast.getPlaintext().setInventoryVector(object.getInventoryVector()); - ctx.getMessageRepository().save(broadcast.getPlaintext()); - listener.receive(broadcast.getPlaintext()); - updatePubkey(broadcast.getPlaintext().getFrom(), broadcast.getPlaintext().getFrom().getPubkey()); + receive(object.getInventoryVector(), broadcast.getPlaintext()); } } catch (DecryptionFailedException ignore) { } } } + + protected void receive(InventoryVector iv, Plaintext msg) { + msg.setStatus(RECEIVED); + msg.setInventoryVector(iv); + labeler.setLabels(msg); + ctx.getMessageRepository().save(msg); + listener.receive(msg); + updatePubkey(msg.getFrom(), msg.getFrom().getPubkey()); + } } diff --git a/core/src/main/java/ch/dissem/bitmessage/InternalContext.java b/core/src/main/java/ch/dissem/bitmessage/InternalContext.java index 00ec40e..56dd9e9 100644 --- a/core/src/main/java/ch/dissem/bitmessage/InternalContext.java +++ b/core/src/main/java/ch/dissem/bitmessage/InternalContext.java @@ -96,7 +96,7 @@ public class InternalContext { init(cryptography, inventory, nodeRegistry, networkHandler, addressRepository, messageRepository, proofOfWorkRepository, proofOfWorkService, proofOfWorkEngine, - messageCallback, customCommandHandler); + messageCallback, customCommandHandler, builder.labeler); for (BitmessageAddress identity : addressRepository.getIdentities()) { streams.add(identity.getStream()); } diff --git a/core/src/main/java/ch/dissem/bitmessage/ports/DefaultLabeler.java b/core/src/main/java/ch/dissem/bitmessage/ports/DefaultLabeler.java new file mode 100644 index 0000000..1598ce1 --- /dev/null +++ b/core/src/main/java/ch/dissem/bitmessage/ports/DefaultLabeler.java @@ -0,0 +1,68 @@ +/* + * Copyright 2016 Christian Basler + * + * 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 ch.dissem.bitmessage.ports; + +import ch.dissem.bitmessage.InternalContext; +import ch.dissem.bitmessage.entity.Plaintext; +import ch.dissem.bitmessage.entity.valueobject.Label; + +import java.util.Iterator; + +public class DefaultLabeler implements Labeler, InternalContext.ContextHolder { + private InternalContext ctx; + + @Override + public void setLabels(Plaintext msg) { + if (msg.getType() == Plaintext.Type.BROADCAST) { + msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.BROADCAST, Label.Type.UNREAD)); + } else { + msg.addLabels(ctx.getMessageRepository().getLabels(Label.Type.INBOX, Label.Type.UNREAD)); + } + } + + @Override + public void markAsRead(Plaintext msg) { + Iterator