mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 04:18:53 +01:00
Replaced private messages with private groups.
Private messages are now the same as group messages, but groups can be private or public. When a contact is added, a private group is created and designated as the inbox for exchanging private messages with the contact.
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
package net.sf.briar.api;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface AuthorFactory {
|
||||
|
||||
Author createAuthor(String name, byte[] publicKey) throws IOException;
|
||||
Author createAuthor(String name, byte[] publicKey);
|
||||
|
||||
LocalAuthor createLocalAuthor(String name, byte[] publicKey,
|
||||
byte[] privateKey) throws IOException;
|
||||
byte[] privateKey);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ public interface CryptoComponent {
|
||||
byte[] deriveMasterSecret(byte[] theirPublicKey, KeyPair ourKeyPair,
|
||||
boolean alice) throws GeneralSecurityException;
|
||||
|
||||
/** Derives a group salt from the given master secret. */
|
||||
byte[] deriveGroupSalt(byte[] secret);
|
||||
|
||||
/**
|
||||
* Derives an initial secret for the given transport from the given master
|
||||
* secret.
|
||||
|
||||
@@ -48,22 +48,25 @@ public interface DatabaseComponent {
|
||||
void removeListener(DatabaseListener d);
|
||||
|
||||
/**
|
||||
* Stores a contact with the given pseudonym, associated with the given
|
||||
* local pseudonym, and returns an ID for the contact.
|
||||
* Stores a contact associated with the given local and remote pseudonyms,
|
||||
* and returns an ID for the contact.
|
||||
*/
|
||||
ContactId addContact(Author remote, AuthorId local) throws DbException;
|
||||
|
||||
/** Stores an endpoint. */
|
||||
void addEndpoint(Endpoint ep) throws DbException;
|
||||
|
||||
/**
|
||||
* Subscribes to a group, or returns false if the user already has the
|
||||
* maximum number of public subscriptions.
|
||||
*/
|
||||
boolean addGroup(Group g) throws DbException;
|
||||
|
||||
/** Stores a local pseudonym. */
|
||||
void addLocalAuthor(LocalAuthor a) throws DbException;
|
||||
|
||||
/** Stores a locally generated group message. */
|
||||
void addLocalGroupMessage(Message m) throws DbException;
|
||||
|
||||
/** Stores a locally generated private message. */
|
||||
void addLocalPrivateMessage(Message m, ContactId c) throws DbException;
|
||||
/** Stores a local message. */
|
||||
void addLocalMessage(Message m) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores the given temporary secrets and deletes any secrets that have
|
||||
@@ -77,14 +80,17 @@ public interface DatabaseComponent {
|
||||
*/
|
||||
boolean addTransport(TransportId t, long maxLatency) throws DbException;
|
||||
|
||||
/** Returns true if any messages are sendable to the given contact. */
|
||||
boolean containsSendableMessages(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an acknowledgement for the given contact, or returns null if
|
||||
* there are no messages to acknowledge.
|
||||
* Returns an acknowledgement for the given contact, or null if there are
|
||||
* no messages to acknowledge.
|
||||
*/
|
||||
Ack generateAck(ContactId c, int maxMessages) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a batch of raw messages for the given contact, with a total
|
||||
* Returns a batch of raw messages for the given contact, with a total
|
||||
* length less than or equal to the given length, for transmission over a
|
||||
* transport with the given maximum latency. Returns null if there are no
|
||||
* sendable messages that fit in the given length.
|
||||
@@ -93,7 +99,7 @@ public interface DatabaseComponent {
|
||||
long maxLatency) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a batch of raw messages for the given contact from the given
|
||||
* Returns a batch of raw messages for the given contact from the given
|
||||
* collection of requested messages, with a total length less than or equal
|
||||
* to the given length, for transmission over a transport with the given
|
||||
* maximum latency. Any messages that were either added to the batch, or
|
||||
@@ -106,19 +112,19 @@ public interface DatabaseComponent {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an offer for the given contact, or returns null if there are
|
||||
* no messages to offer.
|
||||
* Returns an offer for the given contact, or null if there are no messages
|
||||
* to offer.
|
||||
*/
|
||||
Offer generateOffer(ContactId c, int maxMessages) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a retention ack for the given contact, or returns null if no
|
||||
* Returns a retention ack for the given contact, or null if no retention
|
||||
* ack is due.
|
||||
*/
|
||||
RetentionAck generateRetentionAck(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a retention update for the given contact, for transmission
|
||||
* Returns a retention update for the given contact, for transmission
|
||||
* over a transport with the given latency. Returns null if no update is
|
||||
* due.
|
||||
*/
|
||||
@@ -126,13 +132,13 @@ public interface DatabaseComponent {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a subscription ack for the given contact, or returns null if
|
||||
* no ack is due.
|
||||
* Returns a subscription ack for the given contact, or null if no
|
||||
* subscription ack is due.
|
||||
*/
|
||||
SubscriptionAck generateSubscriptionAck(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a subscription update for the given contact, for transmission
|
||||
* Returns a subscription update for the given contact, for transmission
|
||||
* over a transport with the given latency. Returns null if no update is
|
||||
* due.
|
||||
*/
|
||||
@@ -140,14 +146,14 @@ public interface DatabaseComponent {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a batch of transport acks for the given contact, or returns
|
||||
* null if no acks are due.
|
||||
* Returns a batch of transport acks for the given contact, or null if no
|
||||
* transport acks are due.
|
||||
*/
|
||||
Collection<TransportAck> generateTransportAcks(ContactId c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a batch of transport updates for the given contact, for
|
||||
* Returns a batch of transport updates for the given contact, for
|
||||
* transmission over a transport with the given latency. Returns null if no
|
||||
* updates are due.
|
||||
*/
|
||||
@@ -169,8 +175,20 @@ public interface DatabaseComponent {
|
||||
/** Returns the group with the given ID, if the user subscribes to it. */
|
||||
Group getGroup(GroupId g) throws DbException;
|
||||
|
||||
/** Returns the headers of all messages in the given group. */
|
||||
Collection<GroupMessageHeader> getGroupMessageHeaders(GroupId g)
|
||||
/** Returns all groups to which the user subscribes. */
|
||||
Collection<Group> getGroups() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the ID of the inbox group for the given contact, or null if no
|
||||
* inbox group has been set.
|
||||
*/
|
||||
GroupId getInboxGroup(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all messages in the inbox group for the given
|
||||
* contact, or null if no inbox group has been set.
|
||||
*/
|
||||
Collection<MessageHeader> getInboxMessageHeaders(ContactId c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
@@ -195,11 +213,8 @@ public interface DatabaseComponent {
|
||||
/** Returns the body of the message with the given ID. */
|
||||
byte[] getMessageBody(MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all private messages to or from the given
|
||||
* contact.
|
||||
*/
|
||||
Collection<PrivateMessageHeader> getPrivateMessageHeaders(ContactId c)
|
||||
/** Returns the headers of all messages in the given group. */
|
||||
Collection<MessageHeader> getMessageHeaders(GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/** Returns true if the given message has been read. */
|
||||
@@ -212,24 +227,15 @@ public interface DatabaseComponent {
|
||||
/** Returns all temporary secrets. */
|
||||
Collection<TemporarySecret> getSecrets() throws DbException;
|
||||
|
||||
/** Returns the set of groups to which the user subscribes. */
|
||||
Collection<Group> getSubscriptions() throws DbException;
|
||||
|
||||
/** Returns the maximum latencies of all local transports. */
|
||||
Map<TransportId, Long> getTransportLatencies() throws DbException;
|
||||
|
||||
/** Returns the number of unread messages in each subscribed group. */
|
||||
Map<GroupId, Integer> getUnreadMessageCounts() throws DbException;
|
||||
|
||||
/** Returns the contacts to which the given group is visible. */
|
||||
/** Returns the IDs of all contacts to which the given group is visible. */
|
||||
Collection<ContactId> getVisibility(GroupId g) throws DbException;
|
||||
|
||||
/** Returns the subscriptions that are visible to the given contact. */
|
||||
Collection<GroupId> getVisibleSubscriptions(ContactId c) throws DbException;
|
||||
|
||||
/** Returns true if any messages are sendable to the given contact. */
|
||||
boolean hasSendableMessages(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Increments the outgoing connection counter for the given endpoint
|
||||
* in the given rotation period and returns the old value, or -1 if the
|
||||
@@ -295,6 +301,12 @@ public interface DatabaseComponent {
|
||||
/** Removes a contact (and all associated state) from the database. */
|
||||
void removeContact(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Unsubscribes from a group. Any messages belonging to the group
|
||||
* are deleted from the database.
|
||||
*/
|
||||
void removeGroup(Group g) throws DbException;
|
||||
|
||||
/**
|
||||
* Removes a local pseudonym (and all associated state) from the database.
|
||||
*/
|
||||
@@ -314,8 +326,14 @@ public interface DatabaseComponent {
|
||||
long centre, byte[] bitmap) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given message read or unread and returns true if it was
|
||||
* previously read.
|
||||
* Makes a private group visible to the given contact, adds it to the
|
||||
* contact's subscriptions, and sets it as the inbox group for the contact.
|
||||
*/
|
||||
public void setInboxGroup(ContactId c, Group g) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks a message read or unread and returns true if it was previously
|
||||
* read.
|
||||
*/
|
||||
boolean setReadFlag(MessageId m, boolean read) throws DbException;
|
||||
|
||||
@@ -342,16 +360,4 @@ public interface DatabaseComponent {
|
||||
* current contacts.
|
||||
*/
|
||||
void setVisibleToAll(GroupId g, boolean all) throws DbException;
|
||||
|
||||
/**
|
||||
* Subscribes to the given group, or returns false if the user already has
|
||||
* the maximum number of subscriptions.
|
||||
*/
|
||||
boolean subscribe(Group g) throws DbException;
|
||||
|
||||
/**
|
||||
* Unsubscribes from the given group. Any messages belonging to the group
|
||||
* are deleted from the database.
|
||||
*/
|
||||
void unsubscribe(Group g) throws DbException;
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package net.sf.briar.api.db;
|
||||
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
|
||||
public class GroupMessageHeader extends MessageHeader {
|
||||
|
||||
private final GroupId groupId;
|
||||
|
||||
public GroupMessageHeader(MessageId id, MessageId parent, Author author,
|
||||
String contentType, long timestamp, boolean read,
|
||||
GroupId groupId) {
|
||||
super(id, parent, author, contentType, timestamp, read);
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
/** Returns the ID of the group to which the message belongs. */
|
||||
public GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
package net.sf.briar.api.db;
|
||||
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
|
||||
public abstract class MessageHeader {
|
||||
public class MessageHeader {
|
||||
|
||||
private final MessageId id, parent;
|
||||
private final GroupId groupId;
|
||||
private final Author author;
|
||||
private final String contentType;
|
||||
private final long timestamp;
|
||||
private final boolean read;
|
||||
|
||||
protected MessageHeader(MessageId id, MessageId parent, Author author,
|
||||
String contentType, long timestamp, boolean read) {
|
||||
public MessageHeader(MessageId id, MessageId parent, GroupId groupId,
|
||||
Author author, String contentType, long timestamp, boolean read) {
|
||||
this.id = id;
|
||||
this.parent = parent;
|
||||
this.groupId = groupId;
|
||||
this.author = author;
|
||||
this.contentType = contentType;
|
||||
this.timestamp = timestamp;
|
||||
@@ -34,6 +37,13 @@ public abstract class MessageHeader {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier of the group to which the message belongs.
|
||||
*/
|
||||
public GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message's author, or null if this is an anonymous message.
|
||||
*/
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package net.sf.briar.api.db;
|
||||
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
|
||||
public class PrivateMessageHeader extends MessageHeader {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final boolean incoming;
|
||||
|
||||
public PrivateMessageHeader(MessageId id, MessageId parent, Author author,
|
||||
String contentType, long timestamp, boolean read,
|
||||
ContactId contactId, boolean incoming) {
|
||||
super(id, parent, author, contentType, timestamp, read);
|
||||
this.contactId = contactId;
|
||||
this.incoming = incoming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the contact who is the sender (if incoming) or
|
||||
* recipient (if outgoing) of this message.
|
||||
*/
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
/** Returns true if this is an incoming message. */
|
||||
public boolean isIncoming() {
|
||||
return incoming;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
|
||||
/** An event that is broadcast when a group message is added to the database. */
|
||||
public class GroupMessageAddedEvent extends DatabaseEvent {
|
||||
|
||||
private final Group group;
|
||||
private final boolean incoming;
|
||||
|
||||
public GroupMessageAddedEvent(Group group, boolean incoming) {
|
||||
this.group = group;
|
||||
this.incoming = incoming;
|
||||
}
|
||||
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
public boolean isIncoming() {
|
||||
return incoming;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.AuthorId;
|
||||
|
||||
/** An event that is broadcast when a pseudonym for the user is added. */
|
||||
/** An event that is broadcast when a local pseudonym is added. */
|
||||
public class LocalAuthorAddedEvent extends DatabaseEvent {
|
||||
|
||||
private final AuthorId authorId;
|
||||
|
||||
@@ -2,7 +2,7 @@ package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.AuthorId;
|
||||
|
||||
/** An event that is broadcast when a pseudonym for the user is removed. */
|
||||
/** An event that is broadcast when a local pseudonym is removed. */
|
||||
public class LocalAuthorRemovedEvent extends DatabaseEvent {
|
||||
|
||||
private final AuthorId authorId;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
|
||||
/** An event that is broadcast when a message is added to the database. */
|
||||
public class MessageAddedEvent extends DatabaseEvent {
|
||||
|
||||
private final Group group;
|
||||
private final ContactId contactId;
|
||||
|
||||
public MessageAddedEvent(Group group, ContactId contactId) {
|
||||
this.group = group;
|
||||
this.contactId = contactId;
|
||||
}
|
||||
|
||||
/** Returns the group to which the message belongs. */
|
||||
public Group getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the contact from which the message was received, or
|
||||
* null if the message was locally generated.
|
||||
*/
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when a private message is added to the database.
|
||||
*/
|
||||
public class PrivateMessageAddedEvent extends DatabaseEvent {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final boolean incoming;
|
||||
|
||||
public PrivateMessageAddedEvent(ContactId contactId, boolean incoming) {
|
||||
this.contactId = contactId;
|
||||
this.incoming = incoming;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public boolean isIncoming() {
|
||||
return incoming;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,13 @@ public class Group {
|
||||
private final GroupId id;
|
||||
private final String name;
|
||||
private final byte[] salt;
|
||||
private final boolean isPrivate;
|
||||
|
||||
public Group(GroupId id, String name, byte[] salt) {
|
||||
public Group(GroupId id, String name, byte[] salt, boolean isPrivate) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.salt = salt;
|
||||
this.isPrivate = isPrivate;
|
||||
}
|
||||
|
||||
/** Returns the group's unique identifier. */
|
||||
@@ -31,6 +33,11 @@ public class Group {
|
||||
return salt;
|
||||
}
|
||||
|
||||
/** Returns true if the group is private. */
|
||||
public boolean isPrivate() {
|
||||
return isPrivate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package net.sf.briar.api.messaging;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface GroupFactory {
|
||||
|
||||
/** Creates a group with the given name and a random salt. */
|
||||
Group createGroup(String name) throws IOException;
|
||||
Group createGroup(String name, boolean isPrivate);
|
||||
|
||||
/** Creates a group with the given name and salt. */
|
||||
Group createGroup(String name, byte[] salt) throws IOException;
|
||||
Group createGroup(String name, byte[] salt, boolean isPrivate);
|
||||
}
|
||||
|
||||
@@ -8,17 +8,10 @@ import net.sf.briar.api.crypto.PrivateKey;
|
||||
|
||||
public interface MessageFactory {
|
||||
|
||||
/** Creates a private message. */
|
||||
Message createPrivateMessage(MessageId parent, String contentType,
|
||||
long timestamp, byte[] body) throws IOException,
|
||||
GeneralSecurityException;
|
||||
|
||||
/** Creates an anonymous group message. */
|
||||
Message createAnonymousMessage(MessageId parent, Group group,
|
||||
String contentType, long timestamp, byte[] body) throws IOException,
|
||||
GeneralSecurityException;
|
||||
|
||||
/** Creates a pseudonymous group message. */
|
||||
Message createPseudonymousMessage(MessageId parent, Group group,
|
||||
Author author, PrivateKey privateKey, String contentType,
|
||||
long timestamp, byte[] body) throws IOException,
|
||||
|
||||
@@ -11,7 +11,7 @@ public interface MessagingConstants {
|
||||
*/
|
||||
int MAX_PACKET_LENGTH = MIN_CONNECTION_LENGTH / 2;
|
||||
|
||||
/** The maximum number of groups a user may subscribe to. */
|
||||
/** The maximum number of public groups a user may subscribe to. */
|
||||
int MAX_SUBSCRIPTIONS = 3000;
|
||||
|
||||
/** The maximum length of a group's name in UTF-8 bytes. */
|
||||
|
||||
@@ -5,11 +5,11 @@ import java.util.Collection;
|
||||
/** A packet updating the recipient's view of the sender's subscriptions. */
|
||||
public class SubscriptionUpdate {
|
||||
|
||||
private final Collection<Group> subs;
|
||||
private final Collection<Group> groups;
|
||||
private final long version;
|
||||
|
||||
public SubscriptionUpdate(Collection<Group> subs, long version) {
|
||||
this.subs = subs;
|
||||
public SubscriptionUpdate(Collection<Group> groups, long version) {
|
||||
this.groups = groups;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class SubscriptionUpdate {
|
||||
* has made visible to the recipient.
|
||||
*/
|
||||
public Collection<Group> getGroups() {
|
||||
return subs;
|
||||
return groups;
|
||||
}
|
||||
|
||||
/** Returns the update's version number. */
|
||||
|
||||
@@ -8,19 +8,18 @@ public class UnverifiedMessage {
|
||||
private final MessageId parent;
|
||||
private final Group group;
|
||||
private final Author author;
|
||||
private final String contentType, subject;
|
||||
private final String contentType;
|
||||
private final long timestamp;
|
||||
private final byte[] raw, signature;
|
||||
private final int bodyStart, bodyLength, signedLength;
|
||||
|
||||
public UnverifiedMessage(MessageId parent, Group group, Author author,
|
||||
String contentType, String subject, long timestamp, byte[] raw,
|
||||
byte[] signature, int bodyStart, int bodyLength, int signedLength) {
|
||||
String contentType, long timestamp, byte[] raw, byte[] signature,
|
||||
int bodyStart, int bodyLength, int signedLength) {
|
||||
this.parent = parent;
|
||||
this.group = group;
|
||||
this.author = author;
|
||||
this.contentType = contentType;
|
||||
this.subject = subject;
|
||||
this.timestamp = timestamp;
|
||||
this.raw = raw;
|
||||
this.signature = signature;
|
||||
@@ -58,15 +57,6 @@ public class UnverifiedMessage {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message's subject line, which is created from the first 50
|
||||
* bytes of the message body if the content type is text/plain, or is the
|
||||
* empty string otherwise.
|
||||
*/
|
||||
public String getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
/** Returns the message's timestamp. */
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
|
||||
Reference in New Issue
Block a user