Compare commits

..

1 Commits

Author SHA1 Message Date
Ernir Erlingsson
d5734f90f7 new event handler structure 2016-12-07 23:15:17 +01:00
456 changed files with 7176 additions and 10035 deletions

View File

@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
@@ -129,7 +128,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
@Override
public void start() throws PluginException {
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
// with a message queue, so submit it to the AndroidExecutor
@@ -143,14 +142,13 @@ class DroidtoothPlugin implements DuplexPlugin {
}).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.warning("Interrupted while getting BluetoothAdapter");
throw new PluginException(e);
throw new IOException("Interrupted while getting BluetoothAdapter");
} catch (ExecutionException e) {
throw new PluginException(e);
throw new IOException(e);
}
if (adapter == null) {
LOG.info("Bluetooth is not supported");
throw new PluginException();
return false;
}
running = true;
// Listen for changes to the Bluetooth state
@@ -172,6 +170,7 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Not enabling Bluetooth");
}
}
return true;
}
private void bind() {

View File

@@ -39,13 +39,14 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
@Override
public void start() {
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
appContext.registerReceiver(networkStateReceiver, filter);
return true;
}
@Override

View File

@@ -25,7 +25,6 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
@@ -163,18 +162,14 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public void start() throws PluginException {
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Install or update the assets if necessary
if (!assetsAreUpToDate()) installAssets();
LOG.info("Starting Tor");
// Watch for the auth cookie file being updated
try {
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
} catch (IOException e) {
throw new PluginException(e);
}
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
CountDownLatch latch = new CountDownLatch(1);
FileObserver obs = new WriteObserver(cookieFile, latch);
obs.startWatching();
@@ -187,8 +182,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Process torProcess;
try {
torProcess = Runtime.getRuntime().exec(cmd, env, torDirectory);
} catch (SecurityException | IOException e) {
throw new PluginException(e);
} catch (SecurityException e) {
throw new IOException(e);
}
// Log the process's standard output until it detaches
if (LOG.isLoggable(INFO)) {
@@ -202,39 +197,35 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (exit != 0) {
if (LOG.isLoggable(WARNING))
LOG.warning("Tor exited with value " + exit);
throw new PluginException();
return false;
}
// Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException();
return false;
}
} catch (InterruptedException e) {
LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt();
throw new PluginException();
return false;
}
try {
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// Check whether Tor has already bootstrapped
String phase = controlConnection.getInfo("status/bootstrap-phase");
if (phase != null && phase.contains("PROGRESS=100")) {
LOG.info("Tor has already bootstrapped");
connectionStatus.setBootstrapped();
}
} catch (IOException e) {
throw new PluginException(e);
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// Check whether Tor has already bootstrapped
String phase = controlConnection.getInfo("status/bootstrap-phase");
if (phase != null && phase.contains("PROGRESS=100")) {
LOG.info("Tor has already bootstrapped");
connectionStatus.setBootstrapped();
}
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
@@ -242,6 +233,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
appContext.registerReceiver(networkStateReceiver, filter);
// Bind a server socket to receive incoming hidden service connections
bind();
return true;
}
private boolean assetsAreUpToDate() {
@@ -254,7 +246,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
private void installAssets() throws PluginException {
private void installAssets() throws IOException {
InputStream in = null;
OutputStream out = null;
try {
@@ -277,7 +269,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} catch (IOException e) {
tryToClose(in);
tryToClose(out);
throw new PluginException(e);
throw e;
}
}
@@ -484,7 +476,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public void stop() throws PluginException {
public void stop() throws IOException {
running = false;
tryToClose(socket);
if (networkStateReceiver != null)

View File

@@ -8,34 +8,15 @@ dependencies {
compile "com.google.dagger:dagger:2.0.2"
compile 'com.google.dagger:dagger-compiler:2.0.2'
compile 'com.google.code.findbugs:jsr305:3.0.1'
testCompile 'junit:junit:4.12'
testCompile "org.jmock:jmock:2.8.1"
testCompile "org.jmock:jmock-junit4:2.8.1"
testCompile "org.jmock:jmock-legacy:2.8.1"
testCompile "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3"
}
dependencyVerification {
verify = [
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd'
]
}
// needed to make test output available to bramble-core and briar-core
configurations {
testOutput.extendsFrom(testCompile)
}
task jarTest(type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
classifier = 'test'
}
artifacts {
testOutput jarTest
}

View File

@@ -43,24 +43,6 @@ public interface ContactManager {
*/
Contact getContact(ContactId c) throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
/**
* Returns all active contacts.
*/

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.util.Collection;
@NotNullByDefault
@@ -24,14 +25,14 @@ public interface Plugin {
int getMaxIdleTime();
/**
* Starts the plugin.
* Starts the plugin and returns true if it started successfully.
*/
void start() throws PluginException;
boolean start() throws IOException;
/**
* Stops the plugin.
*/
void stop() throws PluginException;
void stop() throws IOException;
/**
* Returns true if the plugin is running.

View File

@@ -1,15 +0,0 @@
package org.briarproject.bramble.api.plugin;
/**
* An exception that indicates an error starting or stopping a {@link Plugin}.
*/
public class PluginException extends Exception {
public PluginException() {
super();
}
public PluginException(Throwable cause) {
super(cause);
}
}

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.sync;
import java.util.Collection;
/**
* A record acknowledging receipt of one or more {@link Message Messages}.
* A packet acknowledging receipt of one or more {@link Message Messages}.
*/
public class Ack {

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.api.sync;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
public class Group {
public enum Visibility {
@@ -15,8 +13,6 @@ public class Group {
private final byte[] descriptor;
public Group(GroupId id, ClientId clientId, byte[] descriptor) {
if (descriptor.length > MAX_GROUP_DESCRIPTOR_LENGTH)
throw new IllegalArgumentException();
this.id = id;
this.clientId = clientId;
this.descriptor = descriptor;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.sync;
import java.util.Collection;
/**
* A record offering the recipient one or more {@link Message Messages}.
* A packet offering the recipient one or more {@link Message Messages}.
*/
public class Offer {

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface RecordReader {
public interface PacketReader {
boolean eof() throws IOException;
@@ -24,5 +24,4 @@ public interface RecordReader {
boolean hasRequest() throws IOException;
Request readRequest() throws IOException;
}

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface RecordReaderFactory {
public interface PacketReaderFactory {
RecordReader createRecordReader(InputStream in);
PacketReader createPacketReader(InputStream in);
}

View File

@@ -1,13 +1,12 @@
package org.briarproject.bramble.api.sync;
/**
* Record types for the sync protocol.
* Packet types for the sync protocol.
*/
public interface RecordTypes {
public interface PacketTypes {
byte ACK = 0;
byte MESSAGE = 1;
byte OFFER = 2;
byte REQUEST = 3;
}

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface RecordWriter {
public interface PacketWriter {
void writeAck(Ack a) throws IOException;

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.OutputStream;
@NotNullByDefault
public interface RecordWriterFactory {
public interface PacketWriterFactory {
RecordWriter createRecordWriter(OutputStream out);
PacketWriter createPacketWriter(OutputStream out);
}

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.sync;
import java.util.Collection;
/**
* A record requesting one or more {@link Message Messages} from the recipient.
* A packet requesting one or more {@link Message Messages} from the recipient.
*/
public class Request {

View File

@@ -10,17 +10,19 @@ public interface SyncConstants {
byte PROTOCOL_VERSION = 0;
/**
* The length of the record header in bytes.
* The length of the packet header in bytes.
*/
int RECORD_HEADER_LENGTH = 4;
int PACKET_HEADER_LENGTH = 4;
/**
* The maximum length of the record payload in bytes.
* The maximum length of the packet payload in bytes.
*/
int MAX_RECORD_PAYLOAD_LENGTH = 48 * 1024; // 48 KiB
int MAX_PACKET_PAYLOAD_LENGTH = 32 * 1024; // 32 KiB
/** The maximum length of a group descriptor in bytes. */
int MAX_GROUP_DESCRIPTOR_LENGTH = 16 * 1024; // 16 KiB
/**
* The maximum length of a message in bytes.
*/
int MAX_MESSAGE_LENGTH = MAX_PACKET_PAYLOAD_LENGTH - PACKET_HEADER_LENGTH;
/**
* The length of the message header in bytes.
@@ -30,15 +32,10 @@ public interface SyncConstants {
/**
* The maximum length of a message body in bytes.
*/
int MAX_MESSAGE_BODY_LENGTH = 32 * 1024; // 32 KiB
int MAX_MESSAGE_BODY_LENGTH = MAX_MESSAGE_LENGTH - MESSAGE_HEADER_LENGTH;
/**
* The maximum length of a message in bytes.
* The maximum number of message IDs in an ack, offer or request packet.
*/
int MAX_MESSAGE_LENGTH = MESSAGE_HEADER_LENGTH + MAX_MESSAGE_BODY_LENGTH;
/**
* The maximum number of message IDs in an ack, offer or request record.
*/
int MAX_MESSAGE_IDS = MAX_RECORD_PAYLOAD_LENGTH / UniqueId.LENGTH;
int MAX_MESSAGE_IDS = MAX_PACKET_PAYLOAD_LENGTH / UniqueId.LENGTH;
}

View File

@@ -5,7 +5,7 @@ import java.io.IOException;
public interface SyncSession {
/**
* Runs the session. This method returns when there are no more records to
* Runs the session. This method returns when there are no more packets to
* send or receive, or when the {@link #interrupt()} method has been called.
*/
void run() throws IOException;

View File

@@ -1,4 +1,3 @@
bin
build
test.tmp
.settings

View File

@@ -1,8 +1,4 @@
plugins {
id "java"
id "net.ltgt.apt" version "0.9"
id "idea"
}
apply plugin: 'java'
sourceCompatibility = 1.6
targetCompatibility = 1.6
@@ -13,8 +9,6 @@ dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.madgag.spongycastle:core:1.54.0.0'
compile 'com.h2database:h2:1.4.190'
testCompile project(path: ':bramble-api', configuration: 'testOutput')
}
dependencyVerification {
@@ -23,15 +17,3 @@ dependencyVerification {
'com.h2database:h2:23ba495a07bbbb3bd6c3084d10a96dad7a23741b8b6d64b213459a784195a98c'
]
}
// needed to make test output available to bramble-j2se
configurations {
testOutput.extendsFrom(testCompile)
}
task jarTest(type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
classifier = 'test'
}
artifacts {
testOutput jarTest
}

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
@@ -89,32 +88,6 @@ class ContactManagerImpl implements ContactManager {
return contact;
}
@Override
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException {
Transaction txn = db.startTransaction(true);
try {
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
db.commitTransaction(txn);
return c;
} finally {
db.endTransaction(txn);
}
}
@Override
public Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
Collection<Contact> contacts =
db.getContactsByAuthorId(txn, remoteAuthorId);
for (Contact c : contacts) {
if (c.getLocalAuthorId().equals(localAuthorId)) {
return c;
}
}
throw new NoSuchContactException();
}
@Override
public Collection<Contact> getActiveContacts() throws DbException {
Collection<Contact> contacts;

View File

@@ -52,7 +52,7 @@ class KeyAgreementProtocol {
void connectionWaiting();
void initialRecordReceived();
void initialPacketReceived();
}
private final Callbacks callbacks;
@@ -117,7 +117,7 @@ class KeyAgreementProtocol {
private byte[] receiveKey() throws AbortException {
byte[] publicKey = transport.receiveKey();
callbacks.initialRecordReceived();
callbacks.initialPacketReceived();
byte[] expected = crypto.deriveKeyCommitment(publicKey);
if (!Arrays.equals(expected, theirPayload.getCommitment()))
throw new AbortException();

View File

@@ -129,7 +129,7 @@ class KeyAgreementTaskImpl extends Thread implements
}
@Override
public void initialRecordReceived() {
public void initialPacketReceived() {
// We send this here instead of when we create the protocol, so that
// if device A makes a connection after getting device B's payload and
// starts its protocol, device A's UI doesn't change to prevent device B

View File

@@ -95,30 +95,20 @@ class KeyAgreementTransport {
out.flush();
}
private byte[] readRecord(byte expectedType) throws AbortException {
while (true) {
byte[] header = readHeader();
byte version = header[0], type = header[1];
int len = ByteUtils.readUint16(header,
RECORD_HEADER_PAYLOAD_LENGTH_OFFSET);
// Reject unrecognised protocol version
if (version != PROTOCOL_VERSION) throw new AbortException(false);
if (type == ABORT) throw new AbortException(true);
if (type == expectedType) {
try {
return readData(len);
} catch (IOException e) {
throw new AbortException(e);
}
}
// Reject recognised but unexpected record type
if (type == KEY || type == CONFIRM) throw new AbortException(false);
// Skip unrecognised record type
try {
readData(len);
} catch (IOException e) {
throw new AbortException(e);
}
private byte[] readRecord(byte type) throws AbortException {
byte[] header = readHeader();
if (header[0] != PROTOCOL_VERSION)
throw new AbortException(); // TODO handle?
if (header[1] != type) {
// Unexpected packet
throw new AbortException(header[1] == ABORT);
}
int len = ByteUtils.readUint16(header,
RECORD_HEADER_PAYLOAD_LENGTH_OFFSET);
try {
return readData(len);
} catch (IOException e) {
throw new AbortException(e);
}
}

View File

@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.ConnectionManager;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.PluginManager;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
@@ -31,6 +30,7 @@ import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.api.ui.UiCallback;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -193,17 +193,24 @@ class PluginManagerImpl implements PluginManager, Service {
@Override
public void run() {
try {
long start = System.currentTimeMillis();
plugin.start();
long duration = System.currentTimeMillis() - start;
if (LOG.isLoggable(INFO)) {
LOG.info("Starting plugin " + plugin.getId() + " took " +
duration + " ms");
}
} catch (PluginException e) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not start");
LOG.log(WARNING, e.toString(), e);
try {
long start = System.currentTimeMillis();
boolean started = plugin.start();
long duration = System.currentTimeMillis() - start;
if (started) {
if (LOG.isLoggable(INFO)) {
LOG.info("Starting plugin " + plugin.getId()
+ " took " + duration + " ms");
}
} else {
if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin" + plugin.getId()
+ " did not start");
}
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
} finally {
startLatch.countDown();
@@ -239,13 +246,10 @@ class PluginManagerImpl implements PluginManager, Service {
+ " took " + duration + " ms");
}
} catch (InterruptedException e) {
LOG.warning("Interrupted while waiting for plugin to stop");
LOG.warning("Interrupted while waiting for plugin to start");
// This task runs on an executor, so don't reset the interrupt
} catch (PluginException e) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("Plugin " + plugin.getId() + " did not stop");
LOG.log(WARNING, e.toString(), e);
}
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} finally {
stopLatch.countDown();
}

View File

@@ -101,10 +101,11 @@ abstract class TcpPlugin implements DuplexPlugin {
}
@Override
public void start() {
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
bind();
return true;
}
protected void bind() {

View File

@@ -14,7 +14,7 @@ import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.SyncSession;
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
@@ -37,19 +37,19 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
/**
* An outgoing {@link SyncSession} suitable for duplex transports. The session
* offers messages before sending them, keeps its output stream open when there
* are no records to send, and reacts to events that make records available to
* are no packets to send, and reacts to events that make packets available to
* send.
*/
@ThreadSafe
@NotNullByDefault
class DuplexOutgoingSession implements SyncSession, EventListener {
// Check for retransmittable records once every 60 seconds
// Check for retransmittable packets once every 60 seconds
private static final int RETX_QUERY_INTERVAL = 60 * 1000;
private static final Logger LOG =
Logger.getLogger(DuplexOutgoingSession.class.getName());
@@ -67,14 +67,14 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
private final Clock clock;
private final ContactId contactId;
private final int maxLatency, maxIdleTime;
private final RecordWriter recordWriter;
private final PacketWriter packetWriter;
private final BlockingQueue<ThrowingRunnable<IOException>> writerTasks;
private volatile boolean interrupted = false;
DuplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
EventBus eventBus, Clock clock, ContactId contactId, int maxLatency,
int maxIdleTime, RecordWriter recordWriter) {
int maxIdleTime, PacketWriter packetWriter) {
this.db = db;
this.dbExecutor = dbExecutor;
this.eventBus = eventBus;
@@ -82,7 +82,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
this.contactId = contactId;
this.maxLatency = maxLatency;
this.maxIdleTime = maxIdleTime;
this.recordWriter = recordWriter;
this.packetWriter = packetWriter;
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
}
@@ -91,7 +91,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
public void run() throws IOException {
eventBus.addListener(this);
try {
// Start a query for each type of record
// Start a query for each type of packet
dbExecutor.execute(new GenerateAck());
dbExecutor.execute(new GenerateBatch());
dbExecutor.execute(new GenerateOffer());
@@ -100,33 +100,33 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
long nextKeepalive = now + maxIdleTime;
long nextRetxQuery = now + RETX_QUERY_INTERVAL;
boolean dataToFlush = true;
// Write records until interrupted
// Write packets until interrupted
try {
while (!interrupted) {
// Work out how long we should wait for a record
// Work out how long we should wait for a packet
now = clock.currentTimeMillis();
long wait = Math.min(nextKeepalive, nextRetxQuery) - now;
if (wait < 0) wait = 0;
// Flush any unflushed data if we're going to wait
if (wait > 0 && dataToFlush && writerTasks.isEmpty()) {
recordWriter.flush();
packetWriter.flush();
dataToFlush = false;
nextKeepalive = now + maxIdleTime;
}
// Wait for a record
// Wait for a packet
ThrowingRunnable<IOException> task = writerTasks.poll(wait,
MILLISECONDS);
if (task == null) {
now = clock.currentTimeMillis();
if (now >= nextRetxQuery) {
// Check for retransmittable records
// Check for retransmittable packets
dbExecutor.execute(new GenerateBatch());
dbExecutor.execute(new GenerateOffer());
nextRetxQuery = now + RETX_QUERY_INTERVAL;
}
if (now >= nextKeepalive) {
// Flush the stream to keep it alive
recordWriter.flush();
packetWriter.flush();
dataToFlush = false;
nextKeepalive = now + maxIdleTime;
}
@@ -137,9 +137,9 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
dataToFlush = true;
}
}
if (dataToFlush) recordWriter.flush();
if (dataToFlush) packetWriter.flush();
} catch (InterruptedException e) {
LOG.info("Interrupted while waiting for a record to write");
LOG.info("Interrupted while waiting for a packet to write");
Thread.currentThread().interrupt();
}
} finally {
@@ -215,7 +215,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
recordWriter.writeAck(ack);
packetWriter.writeAck(ack);
LOG.info("Sent ack");
dbExecutor.execute(new GenerateAck());
}
@@ -232,7 +232,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
Transaction txn = db.startTransaction(false);
try {
b = db.generateRequestedBatch(txn, contactId,
MAX_RECORD_PAYLOAD_LENGTH, maxLatency);
MAX_PACKET_PAYLOAD_LENGTH, maxLatency);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
@@ -259,7 +259,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
for (byte[] raw : batch) recordWriter.writeMessage(raw);
for (byte[] raw : batch) packetWriter.writeMessage(raw);
LOG.info("Sent batch");
dbExecutor.execute(new GenerateBatch());
}
@@ -303,7 +303,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
recordWriter.writeOffer(offer);
packetWriter.writeOffer(offer);
LOG.info("Sent offer");
dbExecutor.execute(new GenerateOffer());
}
@@ -346,7 +346,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
recordWriter.writeRequest(request);
packetWriter.writeRequest(request);
LOG.info("Sent request");
dbExecutor.execute(new GenerateRequest());
}

View File

@@ -16,7 +16,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.RecordReader;
import org.briarproject.bramble.api.sync.PacketReader;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.SyncSession;
@@ -42,18 +42,18 @@ class IncomingSession implements SyncSession, EventListener {
private final Executor dbExecutor;
private final EventBus eventBus;
private final ContactId contactId;
private final RecordReader recordReader;
private final PacketReader packetReader;
private volatile boolean interrupted = false;
IncomingSession(DatabaseComponent db, Executor dbExecutor,
EventBus eventBus, ContactId contactId,
RecordReader recordReader) {
PacketReader packetReader) {
this.db = db;
this.dbExecutor = dbExecutor;
this.eventBus = eventBus;
this.contactId = contactId;
this.recordReader = recordReader;
this.packetReader = packetReader;
}
@IoExecutor
@@ -61,22 +61,21 @@ class IncomingSession implements SyncSession, EventListener {
public void run() throws IOException {
eventBus.addListener(this);
try {
// Read records until interrupted or EOF
while (!interrupted && !recordReader.eof()) {
if (recordReader.hasAck()) {
Ack a = recordReader.readAck();
// Read packets until interrupted or EOF
while (!interrupted && !packetReader.eof()) {
if (packetReader.hasAck()) {
Ack a = packetReader.readAck();
dbExecutor.execute(new ReceiveAck(a));
} else if (recordReader.hasMessage()) {
Message m = recordReader.readMessage();
} else if (packetReader.hasMessage()) {
Message m = packetReader.readMessage();
dbExecutor.execute(new ReceiveMessage(m));
} else if (recordReader.hasOffer()) {
Offer o = recordReader.readOffer();
} else if (packetReader.hasOffer()) {
Offer o = packetReader.readOffer();
dbExecutor.execute(new ReceiveOffer(o));
} else if (recordReader.hasRequest()) {
Request r = recordReader.readRequest();
} else if (packetReader.hasRequest()) {
Request r = packetReader.readRequest();
dbExecutor.execute(new ReceiveRequest(r));
} else {
// unknown records are ignored in RecordReader#eof()
throw new FormatException();
}
}

View File

@@ -30,15 +30,11 @@ class MessageFactoryImpl implements MessageFactory {
public Message createMessage(GroupId g, long timestamp, byte[] body) {
if (body.length > MAX_MESSAGE_BODY_LENGTH)
throw new IllegalArgumentException();
byte[] timeBytes = new byte[ByteUtils.INT_64_BYTES];
ByteUtils.writeUint64(timestamp, timeBytes, 0);
byte[] idHash =
crypto.hash(MessageId.LABEL, g.getBytes(), timeBytes, body);
MessageId id = new MessageId(idHash);
byte[] raw = new byte[MESSAGE_HEADER_LENGTH + body.length];
System.arraycopy(g.getBytes(), 0, raw, 0, UniqueId.LENGTH);
ByteUtils.writeUint64(timestamp, raw, UniqueId.LENGTH);
System.arraycopy(body, 0, raw, MESSAGE_HEADER_LENGTH, body.length);
MessageId id = new MessageId(crypto.hash(MessageId.LABEL, raw));
return new Message(id, g, timestamp, raw);
}

View File

@@ -0,0 +1,28 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.PacketReader;
import org.briarproject.bramble.api.sync.PacketReaderFactory;
import java.io.InputStream;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@Immutable
@NotNullByDefault
class PacketReaderFactoryImpl implements PacketReaderFactory {
private final CryptoComponent crypto;
@Inject
PacketReaderFactoryImpl(CryptoComponent crypto) {
this.crypto = crypto;
}
@Override
public PacketReader createPacketReader(InputStream in) {
return new PacketReaderImpl(crypto, in);
}
}

View File

@@ -2,14 +2,14 @@ package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.RecordReader;
import org.briarproject.bramble.api.sync.PacketReader;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.util.ByteUtils;
@@ -20,84 +20,66 @@ import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.sync.RecordTypes.ACK;
import static org.briarproject.bramble.api.sync.RecordTypes.MESSAGE;
import static org.briarproject.bramble.api.sync.RecordTypes.OFFER;
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.PacketTypes.ACK;
import static org.briarproject.bramble.api.sync.PacketTypes.MESSAGE;
import static org.briarproject.bramble.api.sync.PacketTypes.OFFER;
import static org.briarproject.bramble.api.sync.PacketTypes.REQUEST;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.sync.SyncConstants.RECORD_HEADER_LENGTH;
@NotThreadSafe
@NotNullByDefault
class RecordReaderImpl implements RecordReader {
class PacketReaderImpl implements PacketReader {
private enum State {BUFFER_EMPTY, BUFFER_FULL, EOF}
private enum State { BUFFER_EMPTY, BUFFER_FULL, EOF }
private final MessageFactory messageFactory;
private final CryptoComponent crypto;
private final InputStream in;
private final byte[] header, payload;
private State state = State.BUFFER_EMPTY;
private int payloadLength = 0;
RecordReaderImpl(MessageFactory messageFactory, InputStream in) {
this.messageFactory = messageFactory;
PacketReaderImpl(CryptoComponent crypto, InputStream in) {
this.crypto = crypto;
this.in = in;
header = new byte[RECORD_HEADER_LENGTH];
payload = new byte[MAX_RECORD_PAYLOAD_LENGTH];
header = new byte[PACKET_HEADER_LENGTH];
payload = new byte[MAX_PACKET_PAYLOAD_LENGTH];
}
private void readRecord() throws IOException {
private void readPacket() throws IOException {
if (state != State.BUFFER_EMPTY) throw new IllegalStateException();
while (true) {
// Read the header
int offset = 0;
while (offset < RECORD_HEADER_LENGTH) {
int read =
in.read(header, offset, RECORD_HEADER_LENGTH - offset);
if (read == -1) {
if (offset > 0) throw new FormatException();
state = State.EOF;
return;
}
offset += read;
}
byte version = header[0], type = header[1];
payloadLength = ByteUtils.readUint16(header, 2);
// Check the protocol version
if (version != PROTOCOL_VERSION) throw new FormatException();
// Check the payload length
if (payloadLength > MAX_RECORD_PAYLOAD_LENGTH)
throw new FormatException();
// Read the payload
offset = 0;
while (offset < payloadLength) {
int read = in.read(payload, offset, payloadLength - offset);
if (read == -1) throw new FormatException();
offset += read;
}
state = State.BUFFER_FULL;
// Return if this is a known record type, otherwise continue
if (type == ACK || type == MESSAGE || type == OFFER ||
type == REQUEST) {
// Read the header
int offset = 0;
while (offset < PACKET_HEADER_LENGTH) {
int read = in.read(header, offset, PACKET_HEADER_LENGTH - offset);
if (read == -1) {
if (offset > 0) throw new FormatException();
state = State.EOF;
return;
}
offset += read;
}
// Check the protocol version
if (header[0] != PROTOCOL_VERSION) throw new FormatException();
// Read the payload length
payloadLength = ByteUtils.readUint16(header, 2);
if (payloadLength > MAX_PACKET_PAYLOAD_LENGTH) throw new FormatException();
// Read the payload
offset = 0;
while (offset < payloadLength) {
int read = in.read(payload, offset, payloadLength - offset);
if (read == -1) throw new FormatException();
offset += read;
}
state = State.BUFFER_FULL;
}
/**
* Returns true if there's another record available or false if we've
* reached the end of the input stream.
* <p>
* If a record is available, it's been read into the buffer by the time
* eof() returns, so the method that called eof() can access the record
* from the buffer, for example to check its type or extract its payload.
*/
@Override
public boolean eof() throws IOException {
if (state == State.BUFFER_EMPTY) readRecord();
if (state == State.BUFFER_EMPTY) readPacket();
if (state == State.BUFFER_EMPTY) throw new IllegalStateException();
return state == State.EOF;
}
@@ -142,12 +124,13 @@ class RecordReaderImpl implements RecordReader {
// Timestamp
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
if (timestamp < 0) throw new FormatException();
// Body
byte[] body = new byte[payloadLength - MESSAGE_HEADER_LENGTH];
System.arraycopy(payload, MESSAGE_HEADER_LENGTH, body, 0,
payloadLength - MESSAGE_HEADER_LENGTH);
// Raw message
byte[] raw = new byte[payloadLength];
System.arraycopy(payload, 0, raw, 0, payloadLength);
state = State.BUFFER_EMPTY;
return messageFactory.createMessage(groupId, timestamp, body);
// Message ID
MessageId messageId = new MessageId(crypto.hash(MessageId.LABEL, raw));
return new Message(messageId, groupId, timestamp, raw);
}
@Override
@@ -171,5 +154,4 @@ class RecordReaderImpl implements RecordReader {
if (!hasRequest()) throw new FormatException();
return new Request(readMessageIds());
}
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.PacketWriterFactory;
import java.io.OutputStream;
@NotNullByDefault
class PacketWriterFactoryImpl implements PacketWriterFactory {
@Override
public PacketWriter createPacketWriter(OutputStream out) {
return new PacketWriterImpl(out);
}
}

View File

@@ -4,8 +4,8 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.RecordTypes;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.PacketTypes;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.util.ByteUtils;
@@ -15,30 +15,30 @@ import java.io.OutputStream;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.sync.RecordTypes.ACK;
import static org.briarproject.bramble.api.sync.RecordTypes.OFFER;
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.RECORD_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.PacketTypes.ACK;
import static org.briarproject.bramble.api.sync.PacketTypes.OFFER;
import static org.briarproject.bramble.api.sync.PacketTypes.REQUEST;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PACKET_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
@NotThreadSafe
@NotNullByDefault
class RecordWriterImpl implements RecordWriter {
class PacketWriterImpl implements PacketWriter {
private final OutputStream out;
private final byte[] header;
private final ByteArrayOutputStream payload;
RecordWriterImpl(OutputStream out) {
PacketWriterImpl(OutputStream out) {
this.out = out;
header = new byte[RECORD_HEADER_LENGTH];
header = new byte[PACKET_HEADER_LENGTH];
header[0] = PROTOCOL_VERSION;
payload = new ByteArrayOutputStream(MAX_RECORD_PAYLOAD_LENGTH);
payload = new ByteArrayOutputStream(MAX_PACKET_PAYLOAD_LENGTH);
}
private void writeRecord(byte recordType) throws IOException {
header[1] = recordType;
private void writePacket(byte packetType) throws IOException {
header[1] = packetType;
ByteUtils.writeUint16(payload.size(), header, 2);
out.write(header);
payload.writeTo(out);
@@ -49,12 +49,12 @@ class RecordWriterImpl implements RecordWriter {
public void writeAck(Ack a) throws IOException {
if (payload.size() != 0) throw new IllegalStateException();
for (MessageId m : a.getMessageIds()) payload.write(m.getBytes());
writeRecord(ACK);
writePacket(ACK);
}
@Override
public void writeMessage(byte[] raw) throws IOException {
header[1] = RecordTypes.MESSAGE;
header[1] = PacketTypes.MESSAGE;
ByteUtils.writeUint16(raw.length, header, 2);
out.write(header);
out.write(raw);
@@ -64,14 +64,14 @@ class RecordWriterImpl implements RecordWriter {
public void writeOffer(Offer o) throws IOException {
if (payload.size() != 0) throw new IllegalStateException();
for (MessageId m : o.getMessageIds()) payload.write(m.getBytes());
writeRecord(OFFER);
writePacket(OFFER);
}
@Override
public void writeRequest(Request r) throws IOException {
if (payload.size() != 0) throw new IllegalStateException();
for (MessageId m : r.getMessageIds()) payload.write(m.getBytes());
writeRecord(REQUEST);
writePacket(REQUEST);
}
@Override

View File

@@ -1,28 +0,0 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.RecordReader;
import org.briarproject.bramble.api.sync.RecordReaderFactory;
import java.io.InputStream;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@Immutable
@NotNullByDefault
class RecordReaderFactoryImpl implements RecordReaderFactory {
private final MessageFactory messageFactory;
@Inject
RecordReaderFactoryImpl(MessageFactory messageFactory) {
this.messageFactory = messageFactory;
}
@Override
public RecordReader createRecordReader(InputStream in) {
return new RecordReaderImpl(messageFactory, in);
}
}

View File

@@ -1,16 +0,0 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.RecordWriterFactory;
import java.io.OutputStream;
@NotNullByDefault
class RecordWriterFactoryImpl implements RecordWriterFactory {
@Override
public RecordWriter createRecordWriter(OutputStream out) {
return new RecordWriterImpl(out);
}
}

View File

@@ -13,7 +13,7 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.SyncSession;
import java.io.IOException;
@@ -29,12 +29,12 @@ import javax.annotation.concurrent.ThreadSafe;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
/**
* An outgoing {@link SyncSession} suitable for simplex transports. The session
* sends messages without offering them first, and closes its output stream
* when there are no more records to send.
* when there are no more packets to send.
*/
@ThreadSafe
@NotNullByDefault
@@ -55,7 +55,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
private final EventBus eventBus;
private final ContactId contactId;
private final int maxLatency;
private final RecordWriter recordWriter;
private final PacketWriter packetWriter;
private final AtomicInteger outstandingQueries;
private final BlockingQueue<ThrowingRunnable<IOException>> writerTasks;
@@ -63,14 +63,14 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
SimplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
EventBus eventBus, ContactId contactId,
int maxLatency, RecordWriter recordWriter) {
int maxLatency, PacketWriter packetWriter) {
this.db = db;
this.dbExecutor = dbExecutor;
this.eventBus = eventBus;
this.contactId = contactId;
this.maxLatency = maxLatency;
this.recordWriter = recordWriter;
outstandingQueries = new AtomicInteger(2); // One per type of record
this.packetWriter = packetWriter;
outstandingQueries = new AtomicInteger(2); // One per type of packet
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
}
@@ -79,19 +79,19 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
public void run() throws IOException {
eventBus.addListener(this);
try {
// Start a query for each type of record
// Start a query for each type of packet
dbExecutor.execute(new GenerateAck());
dbExecutor.execute(new GenerateBatch());
// Write records until interrupted or no more records to write
// Write packets until interrupted or no more packets to write
try {
while (!interrupted) {
ThrowingRunnable<IOException> task = writerTasks.take();
if (task == CLOSE) break;
task.run();
}
recordWriter.flush();
packetWriter.flush();
} catch (InterruptedException e) {
LOG.info("Interrupted while waiting for a record to write");
LOG.info("Interrupted while waiting for a packet to write");
Thread.currentThread().interrupt();
}
} finally {
@@ -157,7 +157,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
recordWriter.writeAck(ack);
packetWriter.writeAck(ack);
LOG.info("Sent ack");
dbExecutor.execute(new GenerateAck());
}
@@ -174,7 +174,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
Transaction txn = db.startTransaction(false);
try {
b = db.generateBatch(txn, contactId,
MAX_RECORD_PAYLOAD_LENGTH, maxLatency);
MAX_PACKET_PAYLOAD_LENGTH, maxLatency);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
@@ -202,7 +202,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
@Override
public void run() throws IOException {
if (interrupted) return;
for (byte[] raw : batch) recordWriter.writeMessage(raw);
for (byte[] raw : batch) packetWriter.writeMessage(raw);
LOG.info("Sent batch");
dbExecutor.execute(new GenerateBatch());
}

View File

@@ -7,8 +7,8 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.RecordReaderFactory;
import org.briarproject.bramble.api.sync.RecordWriterFactory;
import org.briarproject.bramble.api.sync.PacketReaderFactory;
import org.briarproject.bramble.api.sync.PacketWriterFactory;
import org.briarproject.bramble.api.sync.SyncSessionFactory;
import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock;
@@ -40,24 +40,23 @@ public class SyncModule {
}
@Provides
RecordReaderFactory provideRecordReaderFactory(
RecordReaderFactoryImpl recordReaderFactory) {
return recordReaderFactory;
PacketReaderFactory providePacketReaderFactory(CryptoComponent crypto) {
return new PacketReaderFactoryImpl(crypto);
}
@Provides
RecordWriterFactory provideRecordWriterFactory() {
return new RecordWriterFactoryImpl();
PacketWriterFactory providePacketWriterFactory() {
return new PacketWriterFactoryImpl();
}
@Provides
@Singleton
SyncSessionFactory provideSyncSessionFactory(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
Clock clock, RecordReaderFactory recordReaderFactory,
RecordWriterFactory recordWriterFactory) {
Clock clock, PacketReaderFactory packetReaderFactory,
PacketWriterFactory packetWriterFactory) {
return new SyncSessionFactoryImpl(db, dbExecutor, eventBus, clock,
recordReaderFactory, recordWriterFactory);
packetReaderFactory, packetWriterFactory);
}
@Provides

View File

@@ -5,10 +5,10 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.RecordReader;
import org.briarproject.bramble.api.sync.RecordReaderFactory;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.RecordWriterFactory;
import org.briarproject.bramble.api.sync.PacketReader;
import org.briarproject.bramble.api.sync.PacketReaderFactory;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.PacketWriterFactory;
import org.briarproject.bramble.api.sync.SyncSession;
import org.briarproject.bramble.api.sync.SyncSessionFactory;
import org.briarproject.bramble.api.system.Clock;
@@ -28,41 +28,41 @@ class SyncSessionFactoryImpl implements SyncSessionFactory {
private final Executor dbExecutor;
private final EventBus eventBus;
private final Clock clock;
private final RecordReaderFactory recordReaderFactory;
private final RecordWriterFactory recordWriterFactory;
private final PacketReaderFactory packetReaderFactory;
private final PacketWriterFactory packetWriterFactory;
@Inject
SyncSessionFactoryImpl(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
Clock clock, RecordReaderFactory recordReaderFactory,
RecordWriterFactory recordWriterFactory) {
Clock clock, PacketReaderFactory packetReaderFactory,
PacketWriterFactory packetWriterFactory) {
this.db = db;
this.dbExecutor = dbExecutor;
this.eventBus = eventBus;
this.clock = clock;
this.recordReaderFactory = recordReaderFactory;
this.recordWriterFactory = recordWriterFactory;
this.packetReaderFactory = packetReaderFactory;
this.packetWriterFactory = packetWriterFactory;
}
@Override
public SyncSession createIncomingSession(ContactId c, InputStream in) {
RecordReader recordReader = recordReaderFactory.createRecordReader(in);
return new IncomingSession(db, dbExecutor, eventBus, c, recordReader);
PacketReader packetReader = packetReaderFactory.createPacketReader(in);
return new IncomingSession(db, dbExecutor, eventBus, c, packetReader);
}
@Override
public SyncSession createSimplexOutgoingSession(ContactId c,
int maxLatency, OutputStream out) {
RecordWriter recordWriter = recordWriterFactory.createRecordWriter(out);
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
return new SimplexOutgoingSession(db, dbExecutor, eventBus, c,
maxLatency, recordWriter);
maxLatency, packetWriter);
}
@Override
public SyncSession createDuplexOutgoingSession(ContactId c, int maxLatency,
int maxIdleTime, OutputStream out) {
RecordWriter recordWriter = recordWriterFactory.createRecordWriter(out);
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(out);
return new DuplexOutgoingSession(db, dbExecutor, eventBus, clock, c,
maxLatency, maxIdleTime, recordWriter);
maxLatency, maxIdleTime, packetWriter);
}
}

View File

@@ -1,50 +0,0 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestSeedProvider;
import org.briarproject.bramble.test.TestUtils;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertFalse;
public class HashTest extends BrambleTestCase {
private final CryptoComponent crypto;
private final String label = TestUtils.getRandomString(42);
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
private final byte[] inputBytes2 = new byte[0];
public HashTest() {
crypto = new CryptoComponentImpl(new TestSeedProvider());
}
@Test
public void testIdenticalInputsProduceIdenticalHashes() {
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
byte[] hash2 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
assertArrayEquals(hash1, hash2);
}
@Test
public void testDifferentInputsProduceDifferentHashes() {
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
byte[] hash2 = crypto.hash(label, inputBytes2, inputBytes1, inputBytes);
assertFalse(Arrays.equals(hash1, hash2));
}
@Test
public void testDifferentLabelsProduceDifferentHashes() {
String label2 = TestUtils.getRandomString(42);
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
byte[] hash2 =
crypto.hash(label2, inputBytes, inputBytes1, inputBytes2);
assertFalse(Arrays.equals(hash1, hash2));
}
}

View File

@@ -1,251 +0,0 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.ByteUtils;
import org.jmock.Expectations;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.RECORD_HEADER_LENGTH;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class KeyAgreementTransportTest extends BrambleMockTestCase {
private final DuplexTransportConnection duplexTransportConnection =
context.mock(DuplexTransportConnection.class);
private final TransportConnectionReader transportConnectionReader =
context.mock(TransportConnectionReader.class);
private final TransportConnectionWriter transportConnectionWriter =
context.mock(TransportConnectionWriter.class);
private final TransportId transportId = new TransportId("test");
private final KeyAgreementConnection keyAgreementConnection =
new KeyAgreementConnection(duplexTransportConnection, transportId);
private ByteArrayInputStream inputStream;
private ByteArrayOutputStream outputStream;
private KeyAgreementTransport kat;
@Test
public void testSendKey() throws Exception {
setup(new byte[0]);
byte[] key = TestUtils.getRandomBytes(123);
kat.sendKey(key);
assertRecordSent(KEY, key);
}
@Test
public void testSendConfirm() throws Exception {
setup(new byte[0]);
byte[] confirm = TestUtils.getRandomBytes(123);
kat.sendConfirm(confirm);
assertRecordSent(CONFIRM, confirm);
}
@Test
public void testSendAbortWithException() throws Exception {
setup(new byte[0]);
context.checking(new Expectations() {{
oneOf(transportConnectionReader).dispose(true, true);
oneOf(transportConnectionWriter).dispose(true);
}});
kat.sendAbort(true);
assertRecordSent(ABORT, new byte[0]);
}
@Test
public void testSendAbortWithoutException() throws Exception {
setup(new byte[0]);
context.checking(new Expectations() {{
oneOf(transportConnectionReader).dispose(false, true);
oneOf(transportConnectionWriter).dispose(false);
}});
kat.sendAbort(false);
assertRecordSent(ABORT, new byte[0]);
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfAtEndOfStream()
throws Exception {
setup(new byte[0]);
kat.receiveKey();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfHeaderIsTooShort()
throws Exception {
byte[] input = new byte[RECORD_HEADER_LENGTH - 1];
input[0] = PROTOCOL_VERSION;
input[1] = KEY;
setup(input);
kat.receiveKey();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfPayloadIsTooShort()
throws Exception {
int payloadLength = 123;
byte[] input = new byte[RECORD_HEADER_LENGTH + payloadLength - 1];
input[0] = PROTOCOL_VERSION;
input[1] = KEY;
ByteUtils.writeUint16(payloadLength, input, 2);
setup(input);
kat.receiveKey();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfProtocolVersionIsUnrecognised()
throws Exception {
setup(createRecord((byte) (PROTOCOL_VERSION + 1), KEY, new byte[123]));
kat.receiveKey();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfAbortIsReceived()
throws Exception {
setup(createRecord(PROTOCOL_VERSION, ABORT, new byte[0]));
kat.receiveKey();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfConfirmIsReceived()
throws Exception {
setup(createRecord(PROTOCOL_VERSION, CONFIRM, new byte[123]));
kat.receiveKey();
}
@Test
public void testReceiveKeySkipsUnrecognisedRecordTypes() throws Exception {
byte[] skip1 = createRecord(PROTOCOL_VERSION, (byte) (ABORT + 1),
new byte[123]);
byte[] skip2 = createRecord(PROTOCOL_VERSION, (byte) (ABORT + 2),
new byte[0]);
byte[] payload = TestUtils.getRandomBytes(123);
byte[] key = createRecord(PROTOCOL_VERSION, KEY, payload);
ByteArrayOutputStream input = new ByteArrayOutputStream();
input.write(skip1);
input.write(skip2);
input.write(key);
setup(input.toByteArray());
assertArrayEquals(payload, kat.receiveKey());
}
@Test(expected = AbortException.class)
public void testReceiveConfirmThrowsExceptionIfAtEndOfStream()
throws Exception {
setup(new byte[0]);
kat.receiveConfirm();
}
@Test(expected = AbortException.class)
public void testReceiveConfirmThrowsExceptionIfHeaderIsTooShort()
throws Exception {
byte[] input = new byte[RECORD_HEADER_LENGTH - 1];
input[0] = PROTOCOL_VERSION;
input[1] = CONFIRM;
setup(input);
kat.receiveConfirm();
}
@Test(expected = AbortException.class)
public void testReceiveConfirmThrowsExceptionIfPayloadIsTooShort()
throws Exception {
int payloadLength = 123;
byte[] input = new byte[RECORD_HEADER_LENGTH + payloadLength - 1];
input[0] = PROTOCOL_VERSION;
input[1] = CONFIRM;
ByteUtils.writeUint16(payloadLength, input, 2);
setup(input);
kat.receiveConfirm();
}
@Test(expected = AbortException.class)
public void testReceiveConfirmThrowsExceptionIfProtocolVersionIsUnrecognised()
throws Exception {
setup(createRecord((byte) (PROTOCOL_VERSION + 1), CONFIRM,
new byte[123]));
kat.receiveConfirm();
}
@Test(expected = AbortException.class)
public void testReceiveConfirmThrowsExceptionIfAbortIsReceived()
throws Exception {
setup(createRecord(PROTOCOL_VERSION, ABORT, new byte[0]));
kat.receiveConfirm();
}
@Test(expected = AbortException.class)
public void testReceiveKeyThrowsExceptionIfKeyIsReceived()
throws Exception {
setup(createRecord(PROTOCOL_VERSION, KEY, new byte[123]));
kat.receiveConfirm();
}
@Test
public void testReceiveConfirmSkipsUnrecognisedRecordTypes()
throws Exception {
byte[] skip1 = createRecord(PROTOCOL_VERSION, (byte) (ABORT + 1),
new byte[123]);
byte[] skip2 = createRecord(PROTOCOL_VERSION, (byte) (ABORT + 2),
new byte[0]);
byte[] payload = TestUtils.getRandomBytes(123);
byte[] confirm = createRecord(PROTOCOL_VERSION, CONFIRM, payload);
ByteArrayOutputStream input = new ByteArrayOutputStream();
input.write(skip1);
input.write(skip2);
input.write(confirm);
setup(input.toByteArray());
assertArrayEquals(payload, kat.receiveConfirm());
}
private void setup(byte[] input) throws Exception {
inputStream = new ByteArrayInputStream(input);
outputStream = new ByteArrayOutputStream();
context.checking(new Expectations() {{
allowing(duplexTransportConnection).getReader();
will(returnValue(transportConnectionReader));
allowing(transportConnectionReader).getInputStream();
will(returnValue(inputStream));
allowing(duplexTransportConnection).getWriter();
will(returnValue(transportConnectionWriter));
allowing(transportConnectionWriter).getOutputStream();
will(returnValue(outputStream));
}});
kat = new KeyAgreementTransport(keyAgreementConnection);
}
private void assertRecordSent(byte expectedType, byte[] expectedPayload) {
byte[] output = outputStream.toByteArray();
assertEquals(RECORD_HEADER_LENGTH + expectedPayload.length,
output.length);
assertEquals(PROTOCOL_VERSION, output[0]);
assertEquals(expectedType, output[1]);
assertEquals(expectedPayload.length, ByteUtils.readUint16(output, 2));
byte[] payload = new byte[output.length - RECORD_HEADER_LENGTH];
System.arraycopy(output, RECORD_HEADER_LENGTH, payload, 0,
payload.length);
assertArrayEquals(expectedPayload, payload);
}
private byte[] createRecord(byte version, byte type, byte[] payload) {
byte[] b = new byte[RECORD_HEADER_LENGTH + payload.length];
b[0] = version;
b[1] = type;
ByteUtils.writeUint16(payload.length, b, 2);
System.arraycopy(payload, 0, b, RECORD_HEADER_LENGTH, payload.length);
return b;
}
}

View File

@@ -1,219 +0,0 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.ByteUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import static org.briarproject.bramble.api.sync.RecordTypes.ACK;
import static org.briarproject.bramble.api.sync.RecordTypes.OFFER;
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.api.sync.SyncConstants.RECORD_HEADER_LENGTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class RecordReaderImplTest extends BrambleMockTestCase {
private final MessageFactory messageFactory =
context.mock(MessageFactory.class);
@Test(expected = FormatException.class)
public void testFormatExceptionIfAckIsTooLarge() throws Exception {
byte[] b = createAck(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readAck();
}
@Test
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
byte[] b = createAck(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readAck();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfAckIsEmpty() throws Exception {
byte[] b = createEmptyAck();
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readAck();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfOfferIsTooLarge() throws Exception {
byte[] b = createOffer(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readOffer();
}
@Test
public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception {
byte[] b = createOffer(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readOffer();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfOfferIsEmpty() throws Exception {
byte[] b = createEmptyOffer();
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readOffer();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfRequestIsTooLarge() throws Exception {
byte[] b = createRequest(true);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readRequest();
}
@Test
public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception {
byte[] b = createRequest(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readRequest();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfRequestIsEmpty() throws Exception {
byte[] b = createEmptyRequest();
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.readRequest();
}
@Test
public void testEofReturnsTrueWhenAtEndOfStream() throws Exception {
ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
assertTrue(reader.eof());
}
@Test
public void testEofReturnsFalseWhenNotAtEndOfStream() throws Exception {
byte[] b = createAck(false);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
assertFalse(reader.eof());
}
@Test(expected = FormatException.class)
public void testThrowsExceptionIfHeaderIsTooShort() throws Exception {
byte[] b = new byte[RECORD_HEADER_LENGTH - 1];
b[0] = PROTOCOL_VERSION;
b[1] = ACK;
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.eof();
}
@Test(expected = FormatException.class)
public void testThrowsExceptionIfPayloadIsTooShort() throws Exception {
int payloadLength = 123;
byte[] b = new byte[RECORD_HEADER_LENGTH + payloadLength - 1];
b[0] = PROTOCOL_VERSION;
b[1] = ACK;
ByteUtils.writeUint16(payloadLength, b, 2);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.eof();
}
@Test(expected = FormatException.class)
public void testThrowsExceptionIfProtocolVersionIsUnrecognised()
throws Exception {
byte version = (byte) (PROTOCOL_VERSION + 1);
byte[] b = createRecord(version, ACK, new byte[0]);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.eof();
}
@Test(expected = FormatException.class)
public void testThrowsExceptionIfPayloadIsTooLong() throws Exception {
byte[] payload = new byte[MAX_RECORD_PAYLOAD_LENGTH + 1];
byte[] b = createRecord(PROTOCOL_VERSION, ACK, payload);
ByteArrayInputStream in = new ByteArrayInputStream(b);
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
reader.eof();
}
@Test
public void testSkipsUnrecognisedRecordTypes() throws Exception {
byte[] skip1 = createRecord(PROTOCOL_VERSION, (byte) (REQUEST + 1),
new byte[123]);
byte[] skip2 = createRecord(PROTOCOL_VERSION, (byte) (REQUEST + 2),
new byte[0]);
byte[] ack = createAck(false);
ByteArrayOutputStream input = new ByteArrayOutputStream();
input.write(skip1);
input.write(skip2);
input.write(ack);
ByteArrayInputStream in = new ByteArrayInputStream(input.toByteArray());
RecordReaderImpl reader = new RecordReaderImpl(messageFactory, in);
assertTrue(reader.hasAck());
Ack a = reader.readAck();
assertEquals(MAX_MESSAGE_IDS, a.getMessageIds().size());
}
private byte[] createAck(boolean tooBig) throws Exception {
return createRecord(PROTOCOL_VERSION, ACK, createPayload(tooBig));
}
private byte[] createEmptyAck() throws Exception {
return createRecord(PROTOCOL_VERSION, ACK, new byte[0]);
}
private byte[] createOffer(boolean tooBig) throws Exception {
return createRecord(PROTOCOL_VERSION, OFFER, createPayload(tooBig));
}
private byte[] createEmptyOffer() throws Exception {
return createRecord(PROTOCOL_VERSION, OFFER, new byte[0]);
}
private byte[] createRequest(boolean tooBig) throws Exception {
return createRecord(PROTOCOL_VERSION, REQUEST, createPayload(tooBig));
}
private byte[] createEmptyRequest() throws Exception {
return createRecord(PROTOCOL_VERSION, REQUEST, new byte[0]);
}
private byte[] createRecord(byte version, byte type, byte[] payload) {
byte[] b = new byte[RECORD_HEADER_LENGTH + payload.length];
b[0] = version;
b[1] = type;
ByteUtils.writeUint16(payload.length, b, 2);
System.arraycopy(payload, 0, b, RECORD_HEADER_LENGTH, payload.length);
return b;
}
private byte[] createPayload(boolean tooBig) throws Exception {
ByteArrayOutputStream payload = new ByteArrayOutputStream();
while (payload.size() + UniqueId.LENGTH <= MAX_RECORD_PAYLOAD_LENGTH) {
payload.write(TestUtils.getRandomId());
}
if (tooBig) payload.write(TestUtils.getRandomId());
assertEquals(tooBig, payload.size() > MAX_RECORD_PAYLOAD_LENGTH);
return payload.toByteArray();
}
}

View File

@@ -7,10 +7,4 @@ apply plugin: 'witness'
dependencies {
compile project(':bramble-core')
compile fileTree(dir: 'libs', include: '*.jar')
testCompile project(path: ':bramble-core', configuration: 'testOutput')
}
tasks.withType(Test) {
systemProperty 'java.library.path', 'libs'
}

View File

@@ -9,7 +9,6 @@ import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
@@ -100,7 +99,7 @@ class BluetoothPlugin implements DuplexPlugin {
}
@Override
public void start() throws PluginException {
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Initialise the Bluetooth stack
try {
@@ -109,14 +108,13 @@ class BluetoothPlugin implements DuplexPlugin {
// On Linux the user may need to install libbluetooth-dev
if (OsUtils.isLinux())
callback.showMessage("BLUETOOTH_INSTALL_LIBS");
throw new PluginException(e);
} catch (BluetoothStateException e) {
throw new PluginException(e);
return false;
}
if (LOG.isLoggable(INFO))
LOG.info("Local address " + localDevice.getBluetoothAddress());
running = true;
bind();
return true;
}
private void bind() {

View File

@@ -2,7 +2,6 @@ package org.briarproject.bramble.plugin.file;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
@@ -43,24 +42,17 @@ class RemovableDrivePlugin extends FilePlugin
}
@Override
public void start() throws PluginException {
public boolean start() throws IOException {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
try {
monitor.start(this);
} catch (IOException e) {
throw new PluginException(e);
}
monitor.start(this);
return true;
}
@Override
public void stop() throws PluginException {
public void stop() throws IOException {
running = false;
try {
monitor.stop();
} catch (IOException e) {
throw new PluginException(e);
}
monitor.stop();
}
@Override

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
@@ -69,7 +68,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
@Override
public void start() throws PluginException {
public boolean start() {
if (used.getAndSet(true)) throw new IllegalStateException();
for (String portName : serialPortList.getPortNames()) {
if (LOG.isLoggable(INFO))
@@ -80,12 +79,12 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
if (LOG.isLoggable(INFO))
LOG.info("Initialised modem on " + portName);
running = true;
return;
return true;
} catch (IOException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
throw new PluginException();
return false;
}
@Override

5
briar-android-tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
bin
gen
build
local.properties
.settings

View File

@@ -0,0 +1,27 @@
apply plugin: 'com.android.library'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 14
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../briar-android/proguard-rules.txt'
consumerProguardFiles getDefaultProguardFile('proguard-android.txt'), '../briar-android/proguard-rules.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
testCompile project(':briar-tests')
testCompile 'junit:junit:4.12'
testCompile 'net.jodah:concurrentunit:0.4.2'
testCompile 'com.android.support:appcompat-v7:23.2.1'
testApt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'javax.annotation:jsr250-api:1.0'
}

View File

@@ -0,0 +1,12 @@
<manifest package="org.briarproject"
xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
>
</application>
</manifest>

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">briar-android-tests</string>
</resources>

View File

@@ -1,15 +1,12 @@
package org.briarproject.briar.blog;
package org.briarproject;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogCommentHeader;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogPost;
import org.briarproject.briar.api.blog.BlogPostHeader;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -20,7 +17,6 @@ import java.util.Iterator;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.test.TestUtils.getRandomString;
import static org.briarproject.briar.api.blog.MessageType.COMMENT;
import static org.briarproject.briar.api.blog.MessageType.POST;
import static org.briarproject.briar.api.blog.MessageType.WRAPPED_COMMENT;
@@ -28,7 +24,7 @@ import static org.briarproject.briar.api.blog.MessageType.WRAPPED_POST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class BlogManagerIntegrationTest
public class BlogManagerTest
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
private BlogManager blogManager0, blogManager1;
@@ -105,7 +101,7 @@ public class BlogManagerIntegrationTest
@Test
public void testBlogPost() throws Exception {
// check that blog0 has no posts
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
Collection<BlogPostHeader> headers0 =
blogManager0.getPostHeaders(blog0.getId());
assertEquals(0, headers0.size());
@@ -143,7 +139,7 @@ public class BlogManagerIntegrationTest
@Test
public void testBlogPostInWrongBlog() throws Exception {
// add a post to blog1
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
BlogPost p = blogPostFactory
.createBlogPost(blog1.getId(), clock.currentTimeMillis(), null,
author0, body);
@@ -169,7 +165,7 @@ public class BlogManagerIntegrationTest
assertFalse(blogManager1.canBeRemoved(blog0.getId()));
// the following two calls should throw a DbException now
thrown.expect(IllegalArgumentException.class);
thrown.expect(DbException.class);
blogManager0.removeBlog(blog1);
blogManager1.removeBlog(blog0);
@@ -182,7 +178,7 @@ public class BlogManagerIntegrationTest
@Test
public void testBlogComment() throws Exception {
// add a post to blog0
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
BlogPost p = blogPostFactory
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
@@ -227,7 +223,7 @@ public class BlogManagerIntegrationTest
@Test
public void testBlogCommentOnOwnPost() throws Exception {
// add a post to blog0
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
BlogPost p = blogPostFactory
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
@@ -263,7 +259,7 @@ public class BlogManagerIntegrationTest
@Test
public void testCommentOnComment() throws Exception {
// add a post to blog0
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
BlogPost p = blogPostFactory
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
@@ -353,7 +349,7 @@ public class BlogManagerIntegrationTest
@Test
public void testCommentOnOwnComment() throws Exception {
// add a post to blog0
final String body = getRandomString(42);
final String body = TestUtils.getRandomString(42);
BlogPost p = blogPostFactory
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);

View File

@@ -1,15 +1,13 @@
package org.briarproject.briar.sharing;
package org.briarproject;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogInvitationRequest;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
@@ -18,9 +16,6 @@ import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationRequestReceivedEvent;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import org.briarproject.briar.api.sharing.InvitationMessage;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -30,13 +25,11 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.briarproject.TestUtils.assertGroupCount;
import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID;
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class BlogSharingIntegrationTest
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
@@ -93,7 +86,7 @@ public class BlogSharingIntegrationTest
injectEagerSingletons(c2);
}
@Test(expected = IllegalArgumentException.class)
@Test
public void testPersonalBlogCannotBeSharedWithOwner() throws Exception {
listenToEvents(true);
@@ -108,8 +101,12 @@ public class BlogSharingIntegrationTest
// create invitation
blogSharingManager0
.sendInvitation(blog1.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog1.getId(), contactId1From0, "Hi!");
// sync invitation
sync0To1(1, false);
// make sure the invitee ignored the request for their own blog
assertFalse(listener1.requestReceived);
}
@Test
@@ -119,8 +116,7 @@ public class BlogSharingIntegrationTest
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
// invitee has own blog and that of the sharer
assertEquals(2, blogManager1.getBlogs().size());
@@ -149,7 +145,7 @@ public class BlogSharingIntegrationTest
// invitee has one invitation message from sharer
List<InvitationMessage> list =
new ArrayList<InvitationMessage>(blogSharingManager1
new ArrayList<>(blogSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
// check other things are alright with the message
@@ -192,8 +188,7 @@ public class BlogSharingIntegrationTest
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, null,
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, null);
// sync first request message
sync0To1(1, true);
@@ -213,7 +208,7 @@ public class BlogSharingIntegrationTest
// invitee has one invitation message from sharer and one response
List<InvitationMessage> list =
new ArrayList<InvitationMessage>(blogSharingManager1
new ArrayList<>(blogSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
// check things are alright with the message
@@ -250,8 +245,7 @@ public class BlogSharingIntegrationTest
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -272,7 +266,7 @@ public class BlogSharingIntegrationTest
assertTrue(blogSharingManager0.getSharedWith(blog2.getId())
.contains(contact1From0));
// invitee gets blog shared by sharer
assertTrue(blogSharingManager1.getSharedWith(blog2.getId())
assertTrue(blogSharingManager1.getSharedBy(blog2.getId())
.contains(contact0From1));
// invitee un-subscribes from blog
@@ -288,12 +282,14 @@ public class BlogSharingIntegrationTest
// sharer no longer shares blog with invitee
assertFalse(blogSharingManager0.getSharedWith(blog2.getId())
.contains(contact1From0));
// invitee no longer has blog shared by sharer
assertEquals(0,
blogSharingManager1.getSharedWith(blog2.getId()).size());
// blog can be shared again by sharer
// invitee no longer gets blog shared by sharer
assertFalse(blogSharingManager1.getSharedBy(blog2.getId())
.contains(contact0From1));
// blog can be shared again
assertTrue(
blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
assertTrue(
blogSharingManager1.canBeShared(blog2.getId(), contact0From1));
}
@Test
@@ -307,18 +303,17 @@ public class BlogSharingIntegrationTest
// sharer sends invitation for 2's blog to 1
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// make sure blog2 is shared by 0 and 2
// make sure blog2 is shared by 0
Collection<Contact> contacts =
blogSharingManager1.getSharedWith(blog2.getId());
assertEquals(2, contacts.size());
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, contacts.size());
assertTrue(contacts.contains(contact0From1));
// make sure 1 knows that they have blog2 already
@@ -344,8 +339,7 @@ public class BlogSharingIntegrationTest
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -361,11 +355,10 @@ public class BlogSharingIntegrationTest
assertEquals(3, blogManager1.getBlogs().size());
Collection<Contact> sharedWith =
blogSharingManager0.getSharedWith(blog2.getId());
assertEquals(2, sharedWith.size());
assertTrue(sharedWith.contains(contact1From0));
assertTrue(sharedWith.contains(contact2From0));
assertEquals(1, sharedWith.size());
assertEquals(contact1From0, sharedWith.iterator().next());
Collection<Contact> sharedBy =
blogSharingManager1.getSharedWith(blog2.getId());
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, sharedBy.size());
assertEquals(contact0From1, sharedBy.iterator().next());
@@ -381,8 +374,7 @@ public class BlogSharingIntegrationTest
// sharer does not share this blog anymore with invitee
sharedWith =
blogSharingManager0.getSharedWith(blog2.getId());
assertEquals(1, sharedWith.size());
assertTrue(sharedWith.contains(contact2From0));
assertEquals(0, sharedWith.size());
}
@Test
@@ -395,8 +387,7 @@ public class BlogSharingIntegrationTest
// sharer sends invitation for 2's blog to 1
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(blog2.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -405,7 +396,7 @@ public class BlogSharingIntegrationTest
// make sure blog2 is shared by 0
Collection<Contact> contacts =
blogSharingManager1.getSharedWith(blog2.getId());
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, contacts.size());
assertTrue(contacts.contains(contact0From1));
@@ -426,65 +417,6 @@ public class BlogSharingIntegrationTest
assertFalse(blogManager1.canBeRemoved(blog2.getId()));
}
@Test
public void testSharerIsInformedWhenBlogIsRemovedDueToContactDeletion()
throws Exception {
// initialize and let invitee accept all requests
listenToEvents(true);
// sharer sends invitation for 2's blog to 1
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
// sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// 1 and 2 are adding each other
addContacts1And2();
assertEquals(3, blogManager1.getBlogs().size());
// make sure blog2 is shared between 0 and 1
Collection<Contact> contacts =
blogSharingManager1.getSharedWith(blog2.getId());
assertEquals(2, contacts.size());
assertTrue(contacts.contains(contact0From1));
contacts = blogSharingManager0.getSharedWith(blog2.getId());
assertEquals(2, contacts.size());
assertTrue(contacts.contains(contact1From0));
// 1 removes contact 2
assertNotNull(contactId2From1);
contactManager1.removeContact(contactId2From1);
// sync leave message to 0
sync1To0(1, true);
// make sure blog2 is no longer shared between 0 and 1
contacts = blogSharingManager0.getSharedWith(blog2.getId());
assertEquals(1, contacts.size());
assertFalse(contacts.contains(contact1From0));
// 1 doesn't even have blog2 anymore
try {
blogManager1.getBlog(blog2.getId());
fail();
} catch (NoSuchGroupException e) {
// expected
}
// 0 can share blog2 again with 1
assertTrue(
blogSharingManager0.canBeShared(blog2.getId(), contact1From0));
}
@NotNullByDefault
private class SharerListener implements EventListener {

View File

@@ -1,4 +1,6 @@
package org.briarproject.briar.test;
package org.briarproject;
import android.support.annotation.CallSuper;
import net.jodah.concurrentunit.Waiter;
@@ -29,8 +31,6 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.api.blog.BlogPostFactory;
@@ -60,10 +60,11 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import static junit.framework.Assert.assertNotNull;
import static org.briarproject.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.TestUtils.getSecretKey;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertTrue;
@MethodsNotNullByDefault
@@ -100,19 +101,19 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
@Inject
protected AuthorFactory authorFactory;
@Inject
protected ContactGroupFactory contactGroupFactory;
ContactGroupFactory contactGroupFactory;
@Inject
protected PrivateGroupFactory privateGroupFactory;
PrivateGroupFactory privateGroupFactory;
@Inject
protected GroupMessageFactory groupMessageFactory;
GroupMessageFactory groupMessageFactory;
@Inject
protected GroupInvitationFactory groupInvitationFactory;
GroupInvitationFactory groupInvitationFactory;
@Inject
protected BlogFactory blogFactory;
BlogFactory blogFactory;
@Inject
protected BlogPostFactory blogPostFactory;
BlogPostFactory blogPostFactory;
@Inject
protected ForumPostFactory forumPostFactory;
ForumPostFactory forumPostFactory;
// objects accessed from background threads need to be volatile
private volatile Waiter validationWaiter;
@@ -131,6 +132,7 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
protected File t2Dir = new File(testDir, AUTHOR2);
@Before
@CallSuper
public void setUp() throws Exception {
assertTrue(testDir.mkdirs());
createComponents();
@@ -325,7 +327,7 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Create an outgoing sync session
SyncSession sessionFrom =
fromSync.createSimplexOutgoingSession(toId, TestPluginConfigModule.MAX_LATENCY, out);
fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out);
// Write whatever needs to be written
sessionFrom.run();
out.close();

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.test;
package org.briarproject;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactManager;
@@ -19,9 +19,6 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogSharingManager;

View File

@@ -1,15 +1,13 @@
package org.briarproject.briar.forum;
package org.briarproject;
import junit.framework.Assert;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.forum.Forum;
import org.briarproject.briar.api.forum.ForumManager;
import org.briarproject.briar.api.forum.ForumPost;
import org.briarproject.briar.api.forum.ForumPostHeader;
import org.briarproject.briar.api.forum.ForumSharingManager;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Test;
@@ -17,10 +15,10 @@ import java.util.Collection;
import javax.annotation.Nullable;
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static junit.framework.TestCase.assertFalse;
import static org.briarproject.TestUtils.assertGroupCount;
import static org.junit.Assert.assertTrue;
public class ForumManagerTest
@@ -45,8 +43,7 @@ public class ForumManagerTest
forum0 = forumManager0.addForum("Test Forum");
groupId0 = forum0.getId();
// share forum
forumSharingManager0.sendInvitation(groupId0, contactId1From0, null,
clock.currentTimeMillis());
forumSharingManager0.sendInvitation(groupId0, contactId1From0, null);
sync0To1(1, true);
forumSharingManager1.respondToInvitation(forum0, contact0From1, true);
sync1To0(1, true);
@@ -113,7 +110,7 @@ public class ForumManagerTest
boolean isPost1 = h.getId().equals(post1.getMessage().getId());
boolean isPost2 = h.getId().equals(post2.getMessage().getId());
assertTrue(isPost1 || isPost2);
Assert.assertTrue(isPost1 || isPost2);
if (isPost1) {
assertEquals(h.getTimestamp(), ms1);
assertEquals(body1, hBody);
@@ -190,8 +187,7 @@ public class ForumManagerTest
// share a second forum
Forum forum1 = forumManager0.addForum("Test Forum1");
GroupId g1 = forum1.getId();
forumSharingManager0.sendInvitation(g1, contactId1From0, null,
clock.currentTimeMillis());
forumSharingManager0.sendInvitation(g1, contactId1From0, null);
sync0To1(1, true);
forumSharingManager1.respondToInvitation(forum1, contact0From1, true);
sync1To0(1, true);

View File

@@ -1,14 +1,19 @@
package org.briarproject.briar.sharing;
package org.briarproject;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.briar.api.client.MessageQueueManager;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.forum.Forum;
import org.briarproject.briar.api.forum.ForumInvitationRequest;
import org.briarproject.briar.api.forum.ForumInvitationResponse;
@@ -20,9 +25,6 @@ import org.briarproject.briar.api.forum.event.ForumInvitationRequestReceivedEven
import org.briarproject.briar.api.forum.event.ForumInvitationResponseReceivedEvent;
import org.briarproject.briar.api.sharing.InvitationMessage;
import org.briarproject.briar.api.sharing.SharingInvitationItem;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -33,7 +35,9 @@ import java.util.Collection;
import java.util.List;
import static junit.framework.Assert.assertNotNull;
import static org.briarproject.bramble.test.TestUtils.getRandomString;
import static org.briarproject.briar.api.forum.ForumConstants.FORUM_SALT_LENGTH;
import static org.briarproject.briar.api.forum.ForumSharingManager.CLIENT_ID;
import static org.briarproject.briar.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -105,8 +109,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -124,7 +127,7 @@ public class ForumSharingIntegrationTest
// invitee has one invitation message from sharer
List<InvitationMessage> list =
new ArrayList<InvitationMessage>(forumSharingManager1
new ArrayList<>(forumSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
// check other things are alright with the forum message
@@ -136,7 +139,6 @@ public class ForumSharingIntegrationTest
assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1From0, invitation.getContactId());
assertEquals("Hi!", invitation.getMessage());
assertTrue(invitation.canBeOpened());
} else {
ForumInvitationResponse response =
(ForumInvitationResponse) m;
@@ -163,8 +165,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, null,
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, null);
// sync first request message
sync0To1(1, true);
@@ -184,7 +185,7 @@ public class ForumSharingIntegrationTest
// invitee has one invitation message from sharer and one response
List<InvitationMessage> list =
new ArrayList<InvitationMessage>(forumSharingManager1
new ArrayList<>(forumSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
// check things are alright with the forum message
@@ -196,7 +197,6 @@ public class ForumSharingIntegrationTest
assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1From0, invitation.getContactId());
assertEquals(null, invitation.getMessage());
assertFalse(invitation.canBeOpened());
} else {
ForumInvitationResponse response =
(ForumInvitationResponse) m;
@@ -221,65 +221,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
// sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(1, forumManager1.getForums().size());
assertTrue(forumManager1.getForums().contains(forum0));
// sharer shares forum with invitee
assertTrue(forumSharingManager0.getSharedWith(forum0.getId())
.contains(contact1From0));
// invitee gets forum shared by sharer
Contact contact0 = contactManager1.getContact(contactId1From0);
assertTrue(forumSharingManager1.getSharedWith(forum0.getId())
.contains(contact0));
// invitee un-subscribes from forum
forumManager1.removeForum(forum0);
// send leave message to sharer
sync1To0(1, true);
// forum is gone
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumManager1.getForums().size());
// sharer no longer shares forum with invitee
assertFalse(forumSharingManager0.getSharedWith(forum0.getId())
.contains(contact1From0));
// invitee no longer gets forum shared by sharer
assertFalse(forumSharingManager1.getSharedWith(forum0.getId())
.contains(contact0));
// forum can be shared again by sharer
assertTrue(forumSharingManager0
.canBeShared(forum0.getId(), contact1From0));
// invitee that left can not share again
assertFalse(forumSharingManager1
.canBeShared(forum0.getId(), contact0From1));
}
@Test
public void testSharerLeavesAfterFinished() throws Exception {
// initialize and let invitee accept all requests
listenToEvents(true);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, null,
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -302,7 +244,62 @@ public class ForumSharingIntegrationTest
.contains(c1));
// invitee gets forum shared by sharer
Contact contact0 = contactManager1.getContact(contactId1From0);
assertTrue(forumSharingManager1.getSharedWith(forum0.getId())
assertTrue(forumSharingManager1.getSharedBy(forum0.getId())
.contains(contact0));
// invitee un-subscribes from forum
forumManager1.removeForum(forum0);
// send leave message to sharer
sync1To0(1, true);
// forum is gone
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumManager1.getForums().size());
// sharer no longer shares forum with invitee
assertFalse(forumSharingManager0.getSharedWith(forum0.getId())
.contains(c1));
// invitee no longer gets forum shared by sharer
assertFalse(forumSharingManager1.getSharedBy(forum0.getId())
.contains(contact0));
// forum can be shared again
assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1));
Contact c0 = contactManager1.getContact(contactId0From1);
assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0));
}
@Test
public void testSharerLeavesAfterFinished() throws Exception {
// initialize and let invitee accept all requests
listenToEvents(true);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, null);
// sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(1, forumManager1.getForums().size());
assertTrue(forumManager1.getForums().contains(forum0));
// sharer shares forum with invitee
Contact c1 = contactManager0.getContact(contactId1From0);
assertTrue(forumSharingManager0.getSharedWith(forum0.getId())
.contains(c1));
// invitee gets forum shared by sharer
Contact contact0 = contactManager1.getContact(contactId1From0);
assertTrue(forumSharingManager1.getSharedBy(forum0.getId())
.contains(contact0));
// sharer un-subscribes from forum
@@ -320,7 +317,7 @@ public class ForumSharingIntegrationTest
assertFalse(forumSharingManager1.getSharedWith(forum0.getId())
.contains(c0));
// sharer no longer gets forum shared by invitee
assertFalse(forumSharingManager1.getSharedWith(forum0.getId())
assertFalse(forumSharingManager1.getSharedBy(forum0.getId())
.contains(contact0));
// forum can be shared again
assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0));
@@ -333,8 +330,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, null,
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, null);
// sharer un-subscribes from forum
forumManager0.removeForum(forum0);
@@ -358,8 +354,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, null,
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, null);
// sharer un-subscribes from forum
forumManager0.removeForum(forum0);
@@ -374,15 +369,14 @@ public class ForumSharingIntegrationTest
assertEquals(1, forumManager1.getForums().size());
}
@Test(expected = IllegalArgumentException.class)
public void testSharingSameForumWithEachOther() throws Exception {
@Test
public void testSessionIdReuse() throws Exception {
// initialize and let invitee accept all requests
listenToEvents(true);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -397,11 +391,84 @@ public class ForumSharingIntegrationTest
// forum was added successfully
assertEquals(1, forumManager1.getForums().size());
// reset event received state
listener1.requestReceived = false;
// get SessionId from invitation
List<InvitationMessage> list = new ArrayList<>(
forumSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
InvitationMessage msg = list.get(0);
SessionId sessionId = msg.getSessionId();
assertEquals(sessionId, list.get(1).getSessionId());
// get all sorts of stuff needed to send a message
MessageQueueManager queue = c0.getMessageQueueManager();
Contact c1 = contactManager0.getContact(contactId1From0);
Group group = contactGroupFactory.createContactGroup(CLIENT_ID, c1);
long time = clock.currentTimeMillis();
BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION,
sessionId.getBytes(),
TestUtils.getRandomString(42),
TestUtils.getRandomBytes(FORUM_SALT_LENGTH)
);
byte[] body = clientHelper.toByteArray(bodyList);
// add the message to the queue
Transaction txn = db0.startTransaction(false);
try {
queue.sendMessage(txn, group, time, body, new Metadata());
db0.commitTransaction(txn);
} finally {
db0.endTransaction(txn);
}
// actually send the message
sync0To1(1, false);
// make sure there was no new request received
assertFalse(listener1.requestReceived);
}
@Test
public void testSharingSameForumWithEachOther() throws Exception {
// initialize and let invitee accept all requests
listenToEvents(true);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(1, forumManager1.getForums().size());
assertEquals(2,
forumSharingManager0.getInvitationMessages(contactId1From0)
.size());
// invitee now shares same forum back
forumSharingManager1.sendInvitation(forum0.getId(),
contactId0From1,
"I am re-sharing this forum with you.",
clock.currentTimeMillis());
"I am re-sharing this forum with you.");
// sync re-share invitation
sync1To0(1, false);
// make sure that no new request was received
assertFalse(listener0.requestReceived);
assertEquals(2,
forumSharingManager0.getInvitationMessages(contactId1From0)
.size());
assertEquals(0, forumSharingManager0.getInvitations().size());
}
@Test
@@ -411,48 +478,62 @@ public class ForumSharingIntegrationTest
// invitee adds the same forum
Transaction txn = db1.startTransaction(false);
forumManager1.addForum(txn, forum0);
db1.addGroup(txn, forum0.getGroup());
db1.commitTransaction(txn);
db1.endTransaction(txn);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// invitee now shares same forum back
forumSharingManager1.sendInvitation(forum0.getId(),
contactId0From1, "I am re-sharing this forum with you.",
clock.currentTimeMillis());
contactId0From1, "I am re-sharing this forum with you.");
// prevent automatic responses
respond = false;
// find out who should be Alice, because of random keys
Bytes key0 = new Bytes(author0.getPublicKey());
Bytes key1 = new Bytes(author1.getPublicKey());
// only now sync first request message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
boolean alice = key1.compareTo(key0) < 0;
if (alice) {
sync0To1(1, false);
assertFalse(listener1.requestReceived);
} else {
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
}
// sync second invitation which counts as accept
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.requestReceived);
// sync second invitation
alice = key0.compareTo(key1) < 0;
if (alice) {
sync1To0(1, false);
assertFalse(listener0.requestReceived);
// both peers should share the forum with each other now
assertTrue(forumSharingManager0.getSharedWith(forum0.getId())
.contains(contact1From0));
assertTrue(forumSharingManager1.getSharedWith(forum0.getId())
.contains(contact0From1));
// sharer did not receive request, but response to own request
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// and both have each other's invitations (and no response)
assertEquals(2, forumSharingManager0
.getInvitationMessages(contactId1From0).size());
assertEquals(2, forumSharingManager1
.getInvitationMessages(contactId0From1).size());
assertEquals(2, forumSharingManager0
.getInvitationMessages(contactId1From0).size());
assertEquals(3, forumSharingManager1
.getInvitationMessages(contactId0From1).size());
} else {
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.requestReceived);
// there are no more open invitations
assertTrue(forumSharingManager0.getInvitations().isEmpty());
assertTrue(forumSharingManager1.getInvitations().isEmpty());
// send response from sharer to invitee and make sure it arrived
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.responseReceived);
assertEquals(3, forumSharingManager0
.getInvitationMessages(contactId1From0).size());
assertEquals(2, forumSharingManager1
.getInvitationMessages(contactId0From1).size());
}
}
@Test
@@ -462,8 +543,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -480,12 +560,18 @@ public class ForumSharingIntegrationTest
assertEquals(1,
forumSharingManager0.getSharedWith(forum0.getId()).size());
// remember SessionId from invitation
List<InvitationMessage> list = new ArrayList<>(
forumSharingManager1
.getInvitationMessages(contactId0From1));
assertEquals(2, list.size());
InvitationMessage msg = list.get(0);
SessionId sessionId = msg.getSessionId();
assertEquals(sessionId, list.get(1).getSessionId());
// contacts now remove each other
removeAllContacts();
// invitee still has forum
assertEquals(1, forumManager1.getForums().size());
// make sure sharer does share the forum with nobody now
assertEquals(0,
forumSharingManager0.getSharedWith(forum0.getId()).size());
@@ -494,30 +580,35 @@ public class ForumSharingIntegrationTest
addDefaultContacts();
addContacts1And2();
// forum can be shared with contacts again
assertTrue(forumSharingManager0
.canBeShared(forum0.getId(), contact1From0));
assertTrue(forumSharingManager0
.canBeShared(forum0.getId(), contact2From0));
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
// get all sorts of stuff needed to send a message
MessageQueueManager queue = c0.getMessageQueueManager();
Contact c1 = contactManager0.getContact(contactId1From0);
Group group = contactGroupFactory.createContactGroup(CLIENT_ID, c1);
long time = clock.currentTimeMillis();
// sync first request message
// construct a new message re-using the old SessionId
BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION,
sessionId.getBytes(),
TestUtils.getRandomString(42),
TestUtils.getRandomBytes(FORUM_SALT_LENGTH)
);
byte[] body = clientHelper.toByteArray(bodyList);
// add the message to the queue
Transaction txn = db0.startTransaction(false);
try {
queue.sendMessage(txn, group, time, body, new Metadata());
db0.commitTransaction(txn);
} finally {
db0.endTransaction(txn);
}
// actually send the message
sync0To1(1, true);
eventWaiter.await(TIMEOUT, 1);
// make sure the new request was received with the same sessionId
// as proof that the state got deleted along with contacts
assertTrue(listener1.requestReceived);
// sync response back
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// forum is still there
assertEquals(1, forumManager1.getForums().size());
assertEquals(1,
forumSharingManager0.getSharedWith(forum0.getId()).size());
}
@Test
@@ -538,16 +629,14 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
// second sharer sends invitation for same forum
assertTrue(contactId1From2 != null);
forumSharingManager2
.sendInvitation(forum0.getId(), contactId1From2, null,
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From2, null);
// sync second request message
sync2To1(1, true);
@@ -557,6 +646,13 @@ public class ForumSharingIntegrationTest
assertEquals(1, forums.size());
assertEquals(2, forums.iterator().next().getNewSharers().size());
assertEquals(forum0, forums.iterator().next().getShareable());
assertEquals(2,
forumSharingManager1.getSharedBy(forum0.getId()).size());
// make sure both sharers actually share the forum
Collection<Contact> contacts =
forumSharingManager1.getSharedBy(forum0.getId());
assertEquals(2, contacts.size());
// answer second request
assertNotNull(contactId2From1);
@@ -575,11 +671,6 @@ public class ForumSharingIntegrationTest
sync1To0(1, true);
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// make sure both sharers actually share the forum
Collection<Contact> contacts =
forumSharingManager1.getSharedWith(forum0.getId());
assertEquals(2, contacts.size());
}
@Test
@@ -589,8 +680,7 @@ public class ForumSharingIntegrationTest
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -602,7 +692,7 @@ public class ForumSharingIntegrationTest
// sharer posts into the forum
long time = clock.currentTimeMillis();
String body = getRandomString(42);
String body = TestUtils.getRandomString(42);
ForumPost p = forumPostFactory
.createPost(forum0.getId(), time, null, author0,
body);
@@ -621,7 +711,7 @@ public class ForumSharingIntegrationTest
// now invitee creates a post
time = clock.currentTimeMillis();
body = getRandomString(42);
body = TestUtils.getRandomString(42);
p = forumPostFactory
.createPost(forum0.getId(), time, null, author1,
body);
@@ -651,8 +741,7 @@ public class ForumSharingIntegrationTest
// send invitation again
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1From0, "Hi!",
clock.currentTimeMillis());
.sendInvitation(forum0.getId(), contactId1From0, "Hi!");
// sync first request message
sync0To1(1, true);
@@ -664,7 +753,7 @@ public class ForumSharingIntegrationTest
// now invitee creates a post
time = clock.currentTimeMillis();
body = getRandomString(42);
body = TestUtils.getRandomString(42);
p = forumPostFactory
.createPost(forum0.getId(), time, null, author1,
body);
@@ -706,10 +795,8 @@ public class ForumSharingIntegrationTest
requestReceived = true;
Forum f = event.getShareable();
try {
if (respond) {
Contact c = contactManager0.getContact(contactId1From0);
forumSharingManager0.respondToInvitation(f, c, true);
}
Contact c = contactManager0.getContact(contactId1From0);
forumSharingManager0.respondToInvitation(f, c, true);
} catch (DbException ex) {
eventWaiter.rethrow(ex);
} finally {
@@ -723,6 +810,7 @@ public class ForumSharingIntegrationTest
private class InviteeListener implements EventListener {
private volatile boolean requestReceived = false;
private volatile boolean responseReceived = false;
private final boolean accept, answer;
@@ -744,13 +832,13 @@ public class ForumSharingIntegrationTest
if (!answer) return;
Forum f = event.getShareable();
try {
eventWaiter.assertEquals(1,
forumSharingManager1.getInvitations().size());
SharingInvitationItem invitation =
forumSharingManager1.getInvitations().iterator()
.next();
eventWaiter.assertEquals(f, invitation.getShareable());
if (respond) {
eventWaiter.assertEquals(1,
forumSharingManager1.getInvitations().size());
SharingInvitationItem invitation =
forumSharingManager1.getInvitations().iterator()
.next();
eventWaiter.assertEquals(f, invitation.getShareable());
Contact c =
contactManager1
.getContact(event.getContactId());
@@ -767,6 +855,7 @@ public class ForumSharingIntegrationTest
ForumInvitationResponseReceivedEvent event =
(ForumInvitationResponseReceivedEvent) e;
eventWaiter.assertEquals(contactId0From1, event.getContactId());
responseReceived = true;
eventWaiter.resume();
}
}

View File

@@ -1,8 +1,7 @@
package org.briarproject.briar.privategroup.invitation;
package org.briarproject;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.client.ProtocolStateException;
import org.briarproject.briar.api.privategroup.GroupMessage;
import org.briarproject.briar.api.privategroup.PrivateGroup;
@@ -12,10 +11,6 @@ import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import org.briarproject.briar.api.sharing.InvitationMessage;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Test;
@@ -23,11 +18,11 @@ import java.util.Collection;
import javax.annotation.Nullable;
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
import static junit.framework.TestCase.fail;
import static org.briarproject.TestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class GroupInvitationIntegrationTest
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
@@ -98,13 +93,12 @@ public class GroupInvitationIntegrationTest
GroupInvitationRequest request =
(GroupInvitationRequest) messages.iterator().next();
assertEquals(msg, request.getMessage());
assertEquals(author0, request.getShareable().getCreator());
assertEquals(author0, request.getCreator());
assertEquals(timestamp, request.getTimestamp());
assertEquals(contactId0From1, request.getContactId());
assertEquals(privateGroup0.getName(), request.getShareable().getName());
assertEquals(privateGroup0.getName(), request.getGroupName());
assertFalse(request.isLocal());
assertFalse(request.isRead());
assertFalse(request.canBeOpened());
}
@Test
@@ -125,7 +119,7 @@ public class GroupInvitationIntegrationTest
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertTrue(response.isLocal());
assertFalse(response.wasAccepted());
@@ -142,7 +136,7 @@ public class GroupInvitationIntegrationTest
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertEquals(contactId0From1, response.getContactId());
assertFalse(response.isLocal());
assertFalse(response.wasAccepted());
@@ -174,10 +168,8 @@ public class GroupInvitationIntegrationTest
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
} else {
assertTrue(((GroupInvitationRequest) m).canBeOpened());
}
}
assertTrue(foundResponse);
@@ -191,7 +183,7 @@ public class GroupInvitationIntegrationTest
for (InvitationMessage m : messages) {
if (m instanceof GroupInvitationResponse) {
foundResponse = true;
InvitationResponse response = (GroupInvitationResponse) m;
GroupInvitationResponse response = (GroupInvitationResponse) m;
assertTrue(response.wasAccepted());
}
}
@@ -333,9 +325,6 @@ public class GroupInvitationIntegrationTest
// Creator's leave message is delivered to invitee
sync0To1(1, true);
// invitee should have no more open invitations
assertTrue(groupInvitationManager1.getInvitations().isEmpty());
// Invitee declines invitation, but it's no longer open - no exception
// as the action has succeeded
assertEquals(0, groupManager1.getPrivateGroups().size());

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.messaging;
package org.briarproject;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -8,22 +8,19 @@ import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.api.forum.ForumConstants;
import org.briarproject.briar.api.forum.ForumPost;
import org.briarproject.briar.api.forum.ForumPostFactory;
import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.test.BriarTestCase;
import org.junit.Test;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.junit.Assert.assertTrue;
@@ -49,7 +46,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
@Test
public void testPrivateMessageFitsIntoPacket() throws Exception {
// Create a maximum-length private message
GroupId groupId = new GroupId(getRandomId());
GroupId groupId = new GroupId(TestUtils.getRandomId());
long timestamp = Long.MAX_VALUE;
String body =
StringUtils.fromUtf8(new byte[MAX_PRIVATE_MESSAGE_BODY_LENGTH]);
@@ -59,7 +56,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
int length = message.getMessage().getRaw().length;
assertTrue(
length > UniqueId.LENGTH + 8 + MAX_PRIVATE_MESSAGE_BODY_LENGTH);
assertTrue(length <= MAX_RECORD_PAYLOAD_LENGTH);
assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
}
@Test
@@ -73,9 +70,9 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
.createLocalAuthor(authorName, authorPublic,
privateKey.getEncoded());
// Create a maximum-length forum post
GroupId groupId = new GroupId(getRandomId());
GroupId groupId = new GroupId(TestUtils.getRandomId());
long timestamp = Long.MAX_VALUE;
MessageId parent = new MessageId(getRandomId());
MessageId parent = new MessageId(TestUtils.getRandomId());
String body = TestUtils.getRandomString(MAX_FORUM_POST_BODY_LENGTH);
ForumPost post = forumPostFactory.createPost(groupId,
timestamp, parent, author, body);
@@ -85,7 +82,7 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
+ MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH
+ ForumConstants.MAX_CONTENT_TYPE_LENGTH
+ MAX_FORUM_POST_BODY_LENGTH);
assertTrue(length <= MAX_RECORD_PAYLOAD_LENGTH);
assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
}
private static void injectEagerSingletons(

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.messaging;
package org.briarproject;
import org.briarproject.bramble.client.ClientModule;
import org.briarproject.bramble.crypto.CryptoModule;
@@ -8,11 +8,9 @@ import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestLifecycleModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.forum.ForumModule;
import org.briarproject.briar.messaging.MessagingModule;
import javax.inject.Singleton;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.privategroup;
package org.briarproject;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.privategroup.GroupMember;
import org.briarproject.briar.api.privategroup.GroupMessage;
import org.briarproject.briar.api.privategroup.GroupMessageHeader;
@@ -14,9 +13,6 @@ import org.briarproject.briar.api.privategroup.JoinMessageHeader;
import org.briarproject.briar.api.privategroup.PrivateGroup;
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationManager;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Test;

View File

@@ -1,11 +1,10 @@
package org.briarproject.briar.privategroup;
package org.briarproject;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
import org.briarproject.briar.api.privategroup.GroupMember;
import org.briarproject.briar.api.privategroup.GroupMessage;
@@ -13,18 +12,14 @@ import org.briarproject.briar.api.privategroup.GroupMessageHeader;
import org.briarproject.briar.api.privategroup.JoinMessageHeader;
import org.briarproject.briar.api.privategroup.PrivateGroup;
import org.briarproject.briar.api.privategroup.PrivateGroupManager;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import org.briarproject.briar.test.DaggerBriarIntegrationTestComponent;
import org.junit.Before;
import org.junit.Test;
import java.util.Collection;
import static org.briarproject.TestUtils.getRandomBytes;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.briar.api.privategroup.Visibility.INVISIBLE;
import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_CONTACT;
import static org.briarproject.briar.api.privategroup.Visibility.REVEALED_BY_US;
@@ -34,7 +29,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class PrivateGroupManagerIntegrationTest
public class PrivateGroupManagerTest
extends BriarIntegrationTest<BriarIntegrationTestComponent> {
private PrivateGroup privateGroup0;
@@ -42,7 +37,6 @@ public class PrivateGroupManagerIntegrationTest
private PrivateGroupManager groupManager0, groupManager1, groupManager2;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
@@ -133,7 +127,7 @@ public class PrivateGroupManagerIntegrationTest
assertEquals(2, groupManager1.getHeaders(groupId0).size());
// create and add test message with random previousMsgId
MessageId previousMsgId = new MessageId(getRandomId());
MessageId previousMsgId = new MessageId(TestUtils.getRandomId());
msg = groupMessageFactory
.createGroupMessage(groupId0, clock.currentTimeMillis(), null,
author0, "test", previousMsgId);
@@ -164,7 +158,7 @@ public class PrivateGroupManagerIntegrationTest
addGroup();
// create and add test message with random parentMsgId
MessageId parentMsgId = new MessageId(getRandomId());
MessageId parentMsgId = new MessageId(TestUtils.getRandomId());
MessageId previousMsgId = groupManager0.getPreviousMsgId(groupId0);
GroupMessage msg = groupMessageFactory
.createGroupMessage(groupId0, clock.currentTimeMillis(),
@@ -442,9 +436,6 @@ public class PrivateGroupManagerIntegrationTest
Collection<GroupMember> members2 = groupManager2.getMembers(groupId0);
assertEquals(3, members2.size());
// 1 and 2 add each other
addContacts1And2();
// assert that contact relationship is not revealed initially
for (GroupMember m : members1) {
if (m.getAuthor().equals(author2)) {

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.messaging;
package org.briarproject;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
@@ -20,12 +20,10 @@ import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriterFactory;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.test.BriarTestCase;
import org.briarproject.briar.messaging.MessagingModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -36,10 +34,10 @@ import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import static org.briarproject.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.briarproject.bramble.test.TestPluginConfigModule.MAX_LATENCY;
import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.messaging;
package org.briarproject;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.event.EventBus;
@@ -18,13 +18,11 @@ import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.api.messaging.MessagingManager;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.client.BriarClientModule;
import org.briarproject.briar.messaging.MessagingModule;
import javax.inject.Singleton;

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.sync;
package org.briarproject;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -12,16 +12,14 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.RecordReader;
import org.briarproject.bramble.api.sync.RecordReaderFactory;
import org.briarproject.bramble.api.sync.RecordWriter;
import org.briarproject.bramble.api.sync.RecordWriterFactory;
import org.briarproject.bramble.api.sync.PacketReader;
import org.briarproject.bramble.api.sync.PacketReaderFactory;
import org.briarproject.bramble.api.sync.PacketWriter;
import org.briarproject.bramble.api.sync.PacketWriterFactory;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.transport.StreamContext;
import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriterFactory;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.TestUtils;
import org.junit.Test;
import java.io.ByteArrayInputStream;
@@ -33,14 +31,13 @@ import java.util.Collection;
import javax.inject.Inject;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class SyncIntegrationTest extends BrambleTestCase {
public class SyncIntegrationTest extends BriarTestCase {
@Inject
GroupFactory groupFactory;
@@ -51,9 +48,9 @@ public class SyncIntegrationTest extends BrambleTestCase {
@Inject
StreamWriterFactory streamWriterFactory;
@Inject
RecordReaderFactory recordReaderFactory;
PacketReaderFactory packetReaderFactory;
@Inject
RecordWriterFactory recordWriterFactory;
PacketWriterFactory packetWriterFactory;
@Inject
CryptoComponent crypto;
@@ -78,7 +75,7 @@ public class SyncIntegrationTest extends BrambleTestCase {
streamNumber = 123;
// Create a group
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
byte[] descriptor = new byte[0];
Group group = groupFactory.createGroup(clientId, descriptor);
// Add two messages to the group
long timestamp = System.currentTimeMillis();
@@ -99,14 +96,14 @@ public class SyncIntegrationTest extends BrambleTestCase {
headerKey, streamNumber);
OutputStream streamWriter = streamWriterFactory.createStreamWriter(out,
ctx);
RecordWriter recordWriter = recordWriterFactory.createRecordWriter(
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(
streamWriter);
recordWriter.writeAck(new Ack(messageIds));
recordWriter.writeMessage(message.getRaw());
recordWriter.writeMessage(message1.getRaw());
recordWriter.writeOffer(new Offer(messageIds));
recordWriter.writeRequest(new Request(messageIds));
packetWriter.writeAck(new Ack(messageIds));
packetWriter.writeMessage(message.getRaw());
packetWriter.writeMessage(message1.getRaw());
packetWriter.writeOffer(new Offer(messageIds));
packetWriter.writeRequest(new Request(messageIds));
streamWriter.flush();
return out.toByteArray();
@@ -128,31 +125,31 @@ public class SyncIntegrationTest extends BrambleTestCase {
headerKey, streamNumber);
InputStream streamReader = streamReaderFactory.createStreamReader(in,
ctx);
RecordReader recordReader = recordReaderFactory.createRecordReader(
PacketReader packetReader = packetReaderFactory.createPacketReader(
streamReader);
// Read the ack
assertTrue(recordReader.hasAck());
Ack a = recordReader.readAck();
assertTrue(packetReader.hasAck());
Ack a = packetReader.readAck();
assertEquals(messageIds, a.getMessageIds());
// Read the messages
assertTrue(recordReader.hasMessage());
Message m = recordReader.readMessage();
assertTrue(packetReader.hasMessage());
Message m = packetReader.readMessage();
checkMessageEquality(message, m);
assertTrue(recordReader.hasMessage());
m = recordReader.readMessage();
assertTrue(packetReader.hasMessage());
m = packetReader.readMessage();
checkMessageEquality(message1, m);
assertFalse(recordReader.hasMessage());
assertFalse(packetReader.hasMessage());
// Read the offer
assertTrue(recordReader.hasOffer());
Offer o = recordReader.readOffer();
assertTrue(packetReader.hasOffer());
Offer o = packetReader.readOffer();
assertEquals(messageIds, o.getMessageIds());
// Read the request
assertTrue(recordReader.hasRequest());
Request req = recordReader.readRequest();
assertTrue(packetReader.hasRequest());
Request req = packetReader.readRequest();
assertEquals(messageIds, req.getMessageIds());
in.close();

View File

@@ -1,7 +1,7 @@
package org.briarproject.bramble.sync;
package org.briarproject;
import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.transport.TransportModule;
import javax.inject.Singleton;

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.test;
package org.briarproject;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.db.DatabaseExecutor;

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.test;
package org.briarproject;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -18,7 +18,7 @@ import dagger.Module;
import dagger.Provides;
@Module
public class TestLifecycleModule {
class TestLifecycleModule {
@Provides
LifecycleManager provideLifecycleManager() {

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.test;
package org.briarproject;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.test;
package org.briarproject;
import org.briarproject.bramble.api.system.SeedProvider;

View File

@@ -2,6 +2,9 @@ package org.briarproject.briar.introduction;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.BriarIntegrationTest;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestUtils;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.Contact;
@@ -24,8 +27,6 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestUtils;
import org.briarproject.briar.api.client.SessionId;
import org.briarproject.briar.api.introduction.IntroductionManager;
import org.briarproject.briar.api.introduction.IntroductionMessage;
@@ -34,7 +35,6 @@ import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionRequestReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionResponseReceivedEvent;
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
import org.briarproject.briar.test.BriarIntegrationTest;
import org.junit.Before;
import org.junit.Test;
@@ -51,8 +51,9 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static org.briarproject.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.TestUtils.assertGroupCount;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.test.TestPluginConfigModule.TRANSPORT_ID;
import static org.briarproject.briar.api.client.MessageQueueManager.QUEUE_STATE_KEY;
import static org.briarproject.briar.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.briar.api.introduction.IntroductionConstants.GROUP_ID;
@@ -69,7 +70,6 @@ import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE
import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_REQUEST;
import static org.briarproject.briar.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.briar.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE;
import static org.briarproject.briar.test.BriarTestUtils.assertGroupCount;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -454,7 +454,7 @@ public class IntroductionIntegrationTest
assertTrue(listener1.requestReceived);
// get SessionId
List<IntroductionMessage> list = new ArrayList<IntroductionMessage>(
List<IntroductionMessage> list = new ArrayList<>(
introductionManager1.getIntroductionMessages(contactId0From1));
assertEquals(2, list.size());
assertTrue(list.get(0) instanceof IntroductionRequest);
@@ -906,9 +906,7 @@ public class IntroductionIntegrationTest
time);
}
}
} catch (DbException exception) {
eventWaiter.rethrow(exception);
} catch (FormatException exception) {
} catch (DbException | IOException exception) {
eventWaiter.rethrow(exception);
} finally {
eventWaiter.resume();

View File

@@ -1,5 +1,9 @@
package org.briarproject.briar.introduction;
import org.briarproject.BriarIntegrationTestComponent;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestPluginConfigModule;
import org.briarproject.TestSeedProviderModule;
import org.briarproject.bramble.client.ClientModule;
import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoModule;
@@ -11,9 +15,6 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.test.TestDatabaseModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.briarproject.bramble.test.TestSeedProviderModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.briar.blog.BlogModule;
import org.briarproject.briar.client.BriarClientModule;
@@ -22,7 +23,6 @@ import org.briarproject.briar.messaging.MessagingModule;
import org.briarproject.briar.privategroup.PrivateGroupModule;
import org.briarproject.briar.privategroup.invitation.GroupInvitationModule;
import org.briarproject.briar.sharing.SharingModule;
import org.briarproject.briar.test.BriarIntegrationTestComponent;
import javax.inject.Singleton;

View File

@@ -1,157 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 330.00001 330.00001"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="logo_circle.svg"
width="330"
height="330"><metadata
id="metadata61"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs59" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1021"
id="namedview57"
showgrid="false"
inkscape:zoom="1.4333435"
inkscape:cx="137.64067"
inkscape:cy="223.06028"
inkscape:window-x="1440"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1" /><style
type="text/css"
id="style3">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#87C214;}
.st2{fill:#87C214;}
.st3{display:none;fill:#FFFFFF;}
.st4{fill:#95D220;}
.st5{display:none;fill:#95D220;}
</style><circle
style="fill:#ffffff"
id="circle7"
cy="165"
cx="165"
class="st0"
r="165" /><g
id="g4214"
transform="translate(0.2999939,1.2000061)"><g
id="g9"><g
id="g11"><rect
x="94"
y="93.800003"
class="st1"
width="43.700001"
height="43.700001"
id="rect13"
style="display:none;fill:#87c214" /><path
class="st2"
d="M 94,144.5 94,264 c 0,9.7 7.9,17.7 17.7,17.7 l 8.3,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-119.5 -43.7,0 z"
id="path15"
inkscape:connector-curvature="0"
style="fill:#87c214" /><path
class="st2"
d="m 137.7,86.8 0,-22.5 c 0,-9.7 -8,-17.7 -17.7,-17.7 l -8.3,0 C 102,46.6 94,54.6 94,64.3 l 0,22.5 43.7,0 z"
id="path17"
inkscape:connector-curvature="0"
style="fill:#87c214" /></g><path
class="st3"
d="m 120,46.7 c 9.7,0 17.7,8 17.7,17.7 l 0,199.6 c 0,9.7 -8,17.7 -17.7,17.7 l -8.3,0 C 102,281.7 94,273.7 94,264 L 94,64.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 8.3,0 m 0,-6.9 -8.3,0 C 98.1,39.7 87,50.7 87,64.3 L 87,264 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.7 C 144.7,50.7 133.6,39.7 120,39.7 l 0,0 z"
id="path19"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g21"><g
id="g23"><path
class="st2"
d="m 234.7,183.8 0,-119.5 c 0,-9.7 -7.9,-17.7 -17.7,-17.7 l -8.3,0 c -9.7,0 -17.7,8 -17.7,17.7 l 0,119.5 43.7,0 z"
id="path25"
inkscape:connector-curvature="0"
style="fill:#87c214" /><rect
x="191"
y="190.8"
class="st1"
width="43.700001"
height="43.700001"
id="rect27"
style="display:none;fill:#87c214" /><path
class="st2"
d="m 191,241.5 0,22.5 c 0,9.7 8,17.7 17.7,17.7 l 8.3,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-22.5 -43.7,0 z"
id="path29"
inkscape:connector-curvature="0"
style="fill:#87c214" /></g><path
class="st3"
d="m 217,46.7 c 9.7,0 17.7,8 17.7,17.7 l 0,199.6 c 0,9.7 -7.9,17.7 -17.7,17.7 l -8.3,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-199.7 c 0,-9.7 8,-17.7 17.7,-17.7 l 8.3,0 m 0,-6.9 -8.3,0 C 195.1,39.7 184,50.8 184,64.4 l 0,199.6 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.7 C 241.7,50.7 230.6,39.7 217,39.7 l 0,0 z"
id="path31"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g33"><g
id="g35"><path
class="st4"
d="m 87,190.8 -22.5,0 c -9.7,0 -17.7,7.9 -17.7,17.7 l 0,8.3 c 0,9.7 7.9,17.7 17.7,17.7 l 22.5,0 0,-43.7 z"
id="path37"
inkscape:connector-curvature="0"
style="fill:#95d220" /><rect
x="94"
y="190.8"
class="st5"
width="43.700001"
height="43.700001"
id="rect39"
style="display:none;fill:#95d220" /><path
class="st4"
d="m 264.2,190.8 -119.5,0 0,43.7 119.5,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-8.3 c -0.1,-9.7 -8,-17.7 -17.7,-17.7 z"
id="path41"
inkscape:connector-curvature="0"
style="fill:#95d220" /></g><path
class="st3"
d="m 264.2,190.8 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.7,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.7,0 m 0,-7 -199.7,0 c -13.6,0 -24.7,11.1 -24.7,24.7 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 c -0.1,-13.6 -11.1,-24.7 -24.7,-24.7 l 0,0 z"
id="path43"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g45"><g
id="g47"><rect
x="191"
y="93.800003"
class="st5"
width="43.700001"
height="43.700001"
id="rect49"
style="display:none;fill:#95d220" /><path
class="st4"
d="m 184,93.8 -119.5,0 c -9.7,0 -17.7,7.9 -17.7,17.7 l 0,8.3 c 0,9.7 7.9,17.7 17.7,17.7 l 119.5,0 0,-43.7 z"
id="path51"
inkscape:connector-curvature="0"
style="fill:#95d220" /><path
class="st4"
d="m 264.2,93.8 -22.5,0 0,43.7 22.5,0 c 9.7,0 17.7,-7.9 17.7,-17.7 l 0,-8.3 c -0.1,-9.7 -8,-17.7 -17.7,-17.7 z"
id="path53"
inkscape:connector-curvature="0"
style="fill:#95d220" /></g><path
class="st3"
d="m 264.2,93.8 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.7,0 c -9.7,0 -17.7,-7.9 -17.7,-17.7 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.7,0 m 0,-7 -199.7,0 c -13.6,0 -24.7,11.1 -24.7,24.7 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 C 288.8,97.9 277.8,86.8 264.2,86.8 l 0,0 z"
id="path55"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g></g></svg>

Before

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -1,118 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="logo_horizontal_white.svg"
width="138"
height="50"><metadata
id="metadata71"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs69" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1021"
id="namedview67"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.410079"
inkscape:cx="96.786606"
inkscape:cy="117.77539"
inkscape:window-x="1443"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
.st5{fill:#FFFFFF;}
</style><rect
style="display:none;fill:#87c214"
id="rect11"
height="9.279274"
width="9.279274"
class="st0"
y="214.00124"
x="230.02246" /><path
class="st2"
d="m 235.54331,203.97877 c 2.05971,0 3.75843,1.69872 3.75843,3.75842 l 0,42.40437 c 0,2.05971 -1.69872,3.75843 -3.75843,3.75843 l -1.76242,0 c -2.0597,0 -3.75843,-1.69872 -3.75843,-3.75843 l 0,-42.40437 c 0,-2.0597 1.67749,-3.75842 3.73719,-3.75842 l 1.78366,0 m 0,-1.48638 -1.76242,0 c -2.90906,0 -5.24481,2.35697 -5.24481,5.2448 l 0,42.40437 c 0,2.88783 2.35698,5.24481 5.24481,5.24481 l 1.76242,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-42.40437 c -0.0212,-2.88783 -2.35698,-5.2448 -5.24481,-5.2448 l 0,0 z"
id="path17"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#87c214"
id="rect25"
height="9.279274"
width="9.279274"
class="st0"
y="234.59825"
x="250.61948" /><path
class="st2"
d="m 256.14033,203.97877 c 2.0597,0 3.75842,1.69872 3.75842,3.75842 l 0,42.40437 c 0,2.05971 -1.67749,3.75843 -3.75842,3.75843 l -1.76243,0 c -2.0597,0 -3.75842,-1.69872 -3.75842,-3.75843 l 0,-42.40437 c 0,-2.0597 1.69872,-3.75842 3.75842,-3.75842 l 1.76243,0 m 0,-1.48638 -1.76243,0 c -2.88783,0 -5.2448,2.35697 -5.2448,5.2448 l 0,42.40437 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 1.76243,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-42.40437 c -0.0212,-2.88783 -2.35698,-5.2448 -5.24481,-5.2448 l 0,0 z"
id="path29"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect37"
height="9.279274"
width="9.279274"
class="st4"
y="234.59825"
x="230.02246" /><path
class="st2"
d="m 266.14156,234.59825 c 2.0597,0 3.75842,1.67749 3.75842,3.75842 l 0,1.76243 c 0,2.0597 -1.69872,3.75842 -3.75842,3.75842 l -42.38314,0 c -2.0597,0 -3.75842,-1.69872 -3.75842,-3.75842 l 0,-1.76243 c 0,-2.0597 1.67749,-3.75842 3.75842,-3.75842 l 42.38314,0 m 0,-1.48638 -42.38314,0 c -2.88783,0 -5.2448,2.33574 -5.2448,5.22357 l 0,1.76242 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 42.40437,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-1.76242 c -0.0212,-2.88783 -2.37821,-5.22357 -5.26604,-5.22357 l 0,0 z"
id="path41"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect47"
height="9.279274"
width="9.279274"
class="st4"
y="214.00124"
x="250.61948" /><path
class="st2"
d="m 266.14156,214.00123 c 2.0597,0 3.75842,1.67749 3.75842,3.75843 l 0,1.76242 c 0,2.05971 -1.69872,3.75843 -3.75842,3.75843 l -42.38314,0 C 221.67749,223.25927 220,221.58179 220,219.52208 l 0,-1.76242 c 0,-2.0597 1.67749,-3.75843 3.75842,-3.75843 l 42.38314,0 m 0,-1.48638 -42.38314,0 c -2.88783,0 -5.2448,2.33575 -5.2448,5.22357 l 0,1.76243 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 42.40437,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-1.76243 c -0.0212,-2.88782 -2.37821,-5.22357 -5.26604,-5.22357 l 0,0 z"
id="path53"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><path
style="fill:#ffffff"
d="m 57.097656,30.69922 0,19.30078 9.06836,0 c 4.22557,0 6.474893,-2.12355 6.496093,-5.47852 0,-2.14464 -1.017672,-3.78004 -3.013671,-4.67187 l 0,-0.041 c 1.507609,-0.9343 2.166015,-2.10331 2.166015,-3.9082 0,-2.73919 -1.848098,-5.20117 -5.861328,-5.20117 l -8.855469,0 z m 18.75,0 0,19.30078 2.271485,0 0,-7.72852 -0.232422,-0.23437 4.585937,0 c 2.54808,0 4.012966,0.91391 4.947266,2.88867 L 89.820312,50 92.367188,50 89.4375,43.96875 c -0.63702,-1.35898 -1.614284,-2.20763 -2.527344,-2.58984 l 0,-0.043 c 2.1234,-0.55208 3.865235,-2.42042 3.865235,-4.94727 0,-3.80089 -2.951713,-5.68945 -6.476563,-5.68945 l -8.451172,0 z m 18.876953,0 0,19.30078 2.273438,0 0,-19.30078 -2.273438,0 z m 13.419921,0 L 99.650391,50 l 2.484379,0 2.03906,-4.65039 -0.12695,-0.23438 10.57421,0 -0.12695,0.23438 2.03906,4.65039 2.48438,0 -8.47266,-19.30078 -2.40039,0 z m 13.33594,0 0,19.30078 2.27148,0 0,-7.72852 -0.23437,-0.23437 4.58789,0 c 2.54808,0 4.01296,0.91391 4.94726,2.88867 L 135.45117,50 138,50 135.07031,43.96875 c -0.63702,-1.35898 -1.61427,-2.20763 -2.52734,-2.58984 l 0,-0.043 c 2.12341,-0.55208 3.86523,-2.42042 3.86523,-4.94727 0,-3.80089 -2.95171,-5.68945 -6.47656,-5.68945 l -8.45117,0 z m -62.322267,2.14453 6.560547,0 c 2.46315,0 3.759766,0.9967 3.759766,3.03516 0,1.71996 -0.999336,3.10156 -3.759766,3.10156 l -6.560547,0 0.234375,-0.23438 0,-5.66992 -0.234375,-0.23242 z m 18.728516,0 6.433593,0 c 2.378211,0 4.14091,0.97535 4.16211,3.52344 0,2.03846 -1.634356,3.5039 -4.416016,3.5039 l -6.179687,0 0.232422,-0.23242 0,-6.5625 -0.232422,-0.23242 z m 45.652341,0 6.4336,0 c 2.35698,0 4.14062,0.97535 4.14062,3.52344 0,2.03846 -1.61288,3.5039 -4.39453,3.5039 l -6.17969,0 0.23438,-0.23242 0,-6.5625 -0.23438,-0.23242 z m -14.20508,0.21094 0.043,0 0.57227,1.93359 3.39844,7.75 0.23242,0.23242 -8.4707,0 0.23242,-0.23242 3.39843,-7.75 0.59375,-1.93359 z m -50.197261,8.07031 7.007812,0 c 2.84536,0 4.16211,1.3153 4.16211,3.375 0,2.14464 -1.189095,3.33398 -4.140625,3.33398 l -7.029297,0 0.234375,-0.23437 0,-6.24219 -0.234375,-0.23242 z"
id="path57"
inkscape:connector-curvature="0" /><g
id="g4770"
transform="matrix(0.21276595,0,0,0.21276595,32.24269,18.624329)"><path
id="path13-3"
d="m -86.640255,-87.534339 c -9.7,0 -17.701175,7.999219 -17.701175,17.699219 l 0,22.5 43.601565,0 0,-22.5 c 0,-9.7 -7.901562,-17.699219 -17.601562,-17.699219 l -8.298828,0 z m 96.999999,0 c -9.69999995,0 -17.7011699,7.999219 -17.7011699,17.699219 l 0,119.500001 43.6015599,0 0,-119.500001 c 0,-9.7 -7.90156,-17.699219 -17.60156,-17.699219 l -8.29883,0 z m -114.701174,97.800781 0,119.499998 c 0,9.7 7.901175,17.69922 17.701175,17.69922 l 8.298828,0 c 9.7,0 17.701172,-7.99922 17.701172,-17.69922 l 0,-119.499998 -43.701175,0 z m 97.0000041,96.999998 0,22.5 c 0,9.7 8.00116995,17.69922 17.7011699,17.69922 l 8.29883,0 c 9.7,0 17.70117,-7.99922 17.70117,-17.69922 l 0,-22.5 -43.7011699,0 z"
style="fill:#87c214"
inkscape:connector-curvature="0" /><path
id="path35"
d="m -133.84143,-40.33512 c -9.7,0 -17.69922,7.901172 -17.69922,17.701172 l 0,8.298828 c 0,9.7000005 7.89922,17.7011725 17.69922,17.7011725 l 119.500004,0 0,-43.7011725 -119.500004,0 z m 177.101564,0 0,43.7011725 22.5,0 c 9.7,0 17.69922,-7.901172 17.69922,-17.7011725 l 0,-8.298828 c 0,-9.8 -7.99922,-17.701172 -17.69922,-17.701172 l -22.5,0 z M -133.84143,56.664881 c -9.7,0 -17.69922,7.90117 -17.69922,17.70117 l 0,8.29883 c 0,9.7 7.89922,17.701169 17.69922,17.701169 l 22.5,0 0,-43.701169 -22.5,0 z m 80.101565,0 0,43.701169 119.499999,0 c 9.7,0 17.69922,-8.001169 17.69922,-17.701169 l 0,-8.29883 c 0,-9.8 -7.99922,-17.70117 -17.69922,-17.70117 l -119.499999,0 z"
style="fill:#95d220"
inkscape:connector-curvature="0" /></g></svg>

Before

Width:  |  Height:  |  Size: 8.7 KiB

View File

@@ -1,154 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 235 234.99999"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="logo_no_text.svg"
width="235"
height="235"><metadata
id="metadata71"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs69" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1021"
id="namedview67"
showgrid="false"
inkscape:zoom="2"
inkscape:cx="42.80241"
inkscape:cy="93.181868"
inkscape:window-x="1443"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
</style><g
id="g5"
transform="translate(-0.5,0)"><g
id="g7"><g
id="g9"><rect
x="47.700001"
y="47.200001"
class="st0"
width="43.700001"
height="43.700001"
id="rect11"
style="display:none;fill:#87c214" /><path
class="st1"
d="m 47.7,97.8 0,119.5 c 0,9.7 7.9,17.7 17.7,17.7 l 8.3,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-119.5 -43.7,0 z"
id="path13"
inkscape:connector-curvature="0"
style="fill:#87c214" /><path
class="st1"
d="m 91.3,40.2 0,-22.5 C 91.3,8 83.4,0 73.7,0 L 65.4,0 C 55.7,0 47.7,8 47.7,17.7 l 0,22.5 43.6,0 z"
id="path15"
inkscape:connector-curvature="0"
style="fill:#87c214" /></g><path
class="st2"
d="m 73.7,0 c 9.7,0 17.7,8 17.7,17.7 l 0,199.7 c 0,9.7 -8,17.7 -17.7,17.7 l -8.3,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-199.7 C 47.7,8 55.6,0 65.3,0 l 8.4,0 m 0,-7 -8.3,0 C 51.7,-7 40.7,4.1 40.7,17.7 l 0,199.7 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.7 C 98.3,4.1 87.3,-7 73.7,-7 l 0,0 z"
id="path17"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g19"><g
id="g21"><path
class="st1"
d="m 188.3,137.2 0,-119.5 C 188.3,8 180.4,0 170.7,0 l -8.3,0 c -9.7,0 -17.7,8 -17.7,17.7 l 0,119.5 43.6,0 z"
id="path23"
inkscape:connector-curvature="0"
style="fill:#87c214" /><rect
x="144.7"
y="144.2"
class="st0"
width="43.700001"
height="43.700001"
id="rect25"
style="display:none;fill:#87c214" /><path
class="st1"
d="m 144.7,194.8 0,22.5 c 0,9.7 8,17.7 17.7,17.7 l 8.3,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-22.5 -43.7,0 z"
id="path27"
inkscape:connector-curvature="0"
style="fill:#87c214" /></g><path
class="st2"
d="m 170.7,0 c 9.7,0 17.7,8 17.7,17.7 l 0,199.7 c 0,9.7 -7.9,17.7 -17.7,17.7 l -8.3,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-199.7 C 144.7,8 152.7,0 162.4,0 l 8.3,0 m 0,-7 -8.3,0 c -13.6,0 -24.7,11.1 -24.7,24.7 l 0,199.7 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.7 C 195.3,4.1 184.3,-7 170.7,-7 l 0,0 z"
id="path29"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g31"><g
id="g33"><path
class="st3"
d="m 40.7,144.2 -22.5,0 c -9.7,0 -17.7,7.9 -17.7,17.7 l 0,8.3 c 0,9.7 7.9,17.7 17.7,17.7 l 22.5,0 0,-43.7 z"
id="path35"
inkscape:connector-curvature="0"
style="fill:#95d220" /><rect
x="47.700001"
y="144.2"
class="st4"
width="43.700001"
height="43.700001"
id="rect37"
style="display:none;fill:#95d220" /><path
class="st3"
d="m 217.8,144.2 -119.5,0 0,43.7 119.5,0 c 9.7,0 17.7,-8 17.7,-17.7 l 0,-8.3 c 0,-9.8 -8,-17.7 -17.7,-17.7 z"
id="path39"
inkscape:connector-curvature="0"
style="fill:#95d220" /></g><path
class="st2"
d="m 217.8,144.2 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.6,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.6,0 m 0,-7 -199.6,0 c -13.6,0 -24.7,11.1 -24.7,24.7 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 c -0.1,-13.7 -11.2,-24.7 -24.8,-24.7 l 0,0 z"
id="path41"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g><g
id="g43"><g
id="g45"><rect
x="144.7"
y="47.200001"
class="st4"
width="43.700001"
height="43.700001"
id="rect47"
style="display:none;fill:#95d220" /><path
class="st3"
d="m 137.7,47.2 -119.5,0 C 8.5,47.2 0.5,55.1 0.5,64.9 l 0,8.3 c 0,9.7 7.9,17.7 17.7,17.7 l 119.5,0 0,-43.7 z"
id="path49"
inkscape:connector-curvature="0"
style="fill:#95d220" /><path
class="st3"
d="m 217.8,47.2 -22.5,0 0,43.7 22.5,0 c 9.7,0 17.7,-7.9 17.7,-17.7 l 0,-8.3 c 0,-9.8 -8,-17.7 -17.7,-17.7 z"
id="path51"
inkscape:connector-curvature="0"
style="fill:#95d220" /></g><path
class="st2"
d="m 217.8,47.2 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.6,0 C 8.5,90.9 0.5,83 0.5,73.2 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.6,0 m 0,-7 -199.6,0 c -13.6,0 -24.7,11 -24.7,24.6 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 C 242.5,51.2 231.4,40.2 217.8,40.2 l 0,0 z"
id="path53"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /></g></g></svg>

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 235 309.99999"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="logo_vertical_black.svg"
width="235"
height="310"><metadata
id="metadata71"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs69" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1021"
id="namedview67"
showgrid="false"
inkscape:zoom="2"
inkscape:cx="44.30241"
inkscape:cy="167.18188"
inkscape:window-x="1440"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
</style><rect
style="display:none;fill:#87c214"
id="rect11"
height="43.700001"
width="43.700001"
class="st0"
y="47.199989"
x="47.200001" /><path
style="fill:#87c214"
d="M 64.900391 0 C 55.200391 0 47.199219 7.9992183 47.199219 17.699219 L 47.199219 40.199219 L 90.800781 40.199219 L 90.800781 17.699219 C 90.800781 7.9992183 82.899219 -4.7369516e-15 73.199219 0 L 64.900391 0 z M 161.90039 0 C 152.20039 0 144.19922 7.9992183 144.19922 17.699219 L 144.19922 137.19922 L 187.80078 137.19922 L 187.80078 17.699219 C 187.80078 7.9992183 179.89922 -4.7369516e-15 170.19922 0 L 161.90039 0 z M 47.199219 97.800781 L 47.199219 217.30078 C 47.199219 227.00078 55.100391 235 64.900391 235 L 73.199219 235 C 82.899219 235 90.900391 227.00078 90.900391 217.30078 L 90.900391 97.800781 L 47.199219 97.800781 z M 144.19922 194.80078 L 144.19922 217.30078 C 144.19922 227.00078 152.20039 235 161.90039 235 L 170.19922 235 C 179.89922 235 187.90039 227.00078 187.90039 217.30078 L 187.90039 194.80078 L 144.19922 194.80078 z "
id="path13" /><path
class="st2"
d="m 73.2,-1.221e-5 c 9.7,0 17.7,8.00000001 17.7,17.70000021 l 0,199.700002 c 0,9.7 -8,17.7 -17.7,17.7 l -8.3,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-199.700002 C 47.2,7.9999878 55.1,-1.221e-5 64.8,-1.221e-5 l 8.4,0 m 0,-6.99999999 -8.3,0 c -13.7,0 -24.7,11.1 -24.7,24.7000002 l 0,199.700002 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.700002 C 97.8,4.0999878 86.8,-7.0000122 73.2,-7.0000122 l 0,0 z"
id="path17"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#87c214"
id="rect25"
height="43.700001"
width="43.700001"
class="st0"
y="144.19998"
x="144.2" /><path
class="st2"
d="m 170.2,-1.221e-5 c 9.7,0 17.7,8.00000001 17.7,17.70000021 l 0,199.700002 c 0,9.7 -7.9,17.7 -17.7,17.7 l -8.3,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-199.700002 c 0,-9.7000002 8,-17.70000021 17.7,-17.70000021 l 8.3,0 m 0,-6.99999999 -8.3,0 c -13.6,0 -24.7,11.1 -24.7,24.7000002 l 0,199.700002 c 0,13.6 11.1,24.7 24.7,24.7 l 8.3,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-199.700002 C 194.8,4.0999878 183.8,-7.0000122 170.2,-7.0000122 l 0,0 z"
id="path29"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><path
style="fill:#95d220"
d="M 17.699219 47.199219 C 7.9992186 47.199219 2.3684758e-15 55.100391 0 64.900391 L 0 73.199219 C 0 82.899219 7.8992186 90.900391 17.699219 90.900391 L 137.19922 90.900391 L 137.19922 47.199219 L 17.699219 47.199219 z M 194.80078 47.199219 L 194.80078 90.900391 L 217.30078 90.900391 C 227.00078 90.900391 235 82.999219 235 73.199219 L 235 64.900391 C 235 55.100391 227.00078 47.199219 217.30078 47.199219 L 194.80078 47.199219 z M 17.699219 144.19922 C 7.9992186 144.19922 2.3684758e-15 152.10039 0 161.90039 L 0 170.19922 C 0 179.89922 7.8992186 187.90039 17.699219 187.90039 L 40.199219 187.90039 L 40.199219 144.19922 L 17.699219 144.19922 z M 97.800781 144.19922 L 97.800781 187.90039 L 217.30078 187.90039 C 227.00078 187.90039 235 179.89922 235 170.19922 L 235 161.90039 C 235 152.10039 227.00078 144.19922 217.30078 144.19922 L 97.800781 144.19922 z "
id="path35" /><rect
style="display:none;fill:#95d220"
id="rect37"
height="43.700001"
width="43.700001"
class="st4"
y="144.19998"
x="47.200001" /><path
class="st2"
d="m 217.3,144.19999 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.6,0 c -9.7,0 -17.7,-8 -17.7,-17.7 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.6,0 m 0,-7 -199.6,0 c -13.6,0 -24.7,11.1 -24.7,24.7 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 c -0.1,-13.7 -11.2,-24.7 -24.8,-24.7 l 0,0 z"
id="path41"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect47"
height="43.700001"
width="43.700001"
class="st4"
y="47.199989"
x="144.2" /><path
class="st2"
d="m 217.3,47.199988 c 9.7,0 17.7,7.9 17.7,17.7 l 0,8.3 c 0,9.7 -8,17.7 -17.7,17.7 l -199.6,0 c -9.7,0 -17.7,-7.9 -17.7,-17.7 l 0,-8.3 c 0,-9.7 7.9,-17.7 17.7,-17.7 l 199.6,0 m 0,-7 -199.6,0 c -13.6,0 -24.7,11 -24.7,24.6 l 0,8.3 c 0,13.6 11.1,24.7 24.7,24.7 l 199.7,0 c 13.6,0 24.7,-11.1 24.7,-24.7 l 0,-8.3 c -0.1,-13.6 -11.2,-24.6 -24.8,-24.6 l 0,0 z"
id="path53"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><path
d="M 0 253.90039 L 0 310 L 26.265625 310 C 38.649816 310 45.142578 303.79961 45.142578 294.09961 C 45.142578 287.79961 42.24573 283.1 36.453125 280.5 L 36.453125 280.40039 C 40.847515 277.70039 42.746094 274.3 42.746094 269 C 42.746094 261 37.25318 253.90039 25.667969 253.90039 L 0 253.90039 z M 54.53125 253.90039 L 54.53125 310 L 61.121094 310 L 61.121094 287.5 L 60.423828 286.80078 L 73.705078 286.80078 C 81.095643 286.80078 85.291724 289.39922 87.988281 295.19922 L 94.978516 310 L 102.36914 310 L 94.080078 292.5 C 92.282373 288.6 89.385747 286.1 86.789062 285 L 86.789062 284.90039 C 92.881286 283.30039 97.974609 277.8 97.974609 270.5 C 97.974609 259.4 89.386477 253.90039 79.099609 253.90039 L 54.53125 253.90039 z M 109.25977 253.90039 L 109.25977 310 L 115.85156 310 L 115.85156 253.90039 L 109.25977 253.90039 z M 148.01172 253.90039 L 123.3418 310 L 130.5332 310 L 136.52539 296.5 L 136.22656 295.80078 L 166.88672 295.80078 L 166.58789 296.5 L 172.58008 310 L 179.77148 310 L 155.00195 253.90039 L 148.01172 253.90039 z M 187.16016 253.90039 L 187.16016 310 L 193.75195 310 L 193.75195 287.5 L 193.05273 286.80078 L 206.33594 286.80078 C 213.72651 286.80078 217.92258 289.39922 220.61914 295.19922 L 227.60938 310 L 235 310 L 226.71094 292.5 C 224.91324 288.6 222.0166 286.1 219.41992 285 L 219.41992 284.90039 C 225.51214 283.30039 230.60547 277.8 230.60547 270.5 C 230.60547 259.4 222.01733 253.90039 211.73047 253.90039 L 187.16016 253.90039 z M 5.8925781 260.09961 L 24.96875 260.09961 C 32.15957 260.09961 35.953125 263 35.953125 269 C 35.953125 274 32.95855 278 24.96875 278 L 5.8925781 278 L 6.5917969 277.30078 L 6.5917969 260.80078 L 5.8925781 260.09961 z M 60.423828 260.09961 L 79.099609 260.09961 C 85.89094 260.09961 91.083724 262.90039 91.183594 270.40039 C 91.183594 276.40039 86.490064 280.59961 78.400391 280.59961 L 60.423828 280.59961 L 61.121094 279.90039 L 61.121094 260.80078 L 60.423828 260.09961 z M 192.95312 260.09961 L 211.62891 260.09961 C 218.52012 260.09961 223.71484 262.90039 223.71484 270.40039 C 223.71484 276.40039 219.02131 280.59961 210.93164 280.59961 L 192.95312 280.59961 L 193.65234 279.90039 L 193.65234 260.80078 L 192.95312 260.09961 z M 151.60547 260.80078 L 151.70703 260.80078 L 153.4043 266.40039 L 163.29102 288.90039 L 163.99023 289.59961 L 139.32227 289.59961 L 140.02148 288.90039 L 149.9082 266.40039 L 151.60547 260.80078 z M 5.8925781 284.19922 L 26.265625 284.19922 C 34.555043 284.19922 38.351562 287.99961 38.351562 294.09961 C 38.351562 300.29961 34.854661 303.80078 26.265625 303.80078 L 5.8925781 303.80078 L 6.5917969 303.09961 L 6.5917969 284.90039 L 5.8925781 284.19922 z "
id="path57" /></svg>

Before

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'witness'
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
def supportVersion = '23.2.1'
@@ -29,12 +30,16 @@ dependencies {
compile 'info.guardianproject.trustedintents:trustedintents:0.2'
compile 'de.hdodenhof:circleimageview:2.1.0'
compile 'com.google.zxing:core:3.2.1'
apt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'javax.annotation:jsr250-api:1.0'
compile 'com.jpardogo.materialtabstrip:library:1.1.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'uk.co.samuelwall:material-tap-target-prompt:1.3.0'
testCompile project(path: ':bramble-core', configuration: 'testOutput')
testCompile 'junit:junit:4.12'
testCompile 'net.jodah:concurrentunit:0.4.2'
testApt 'com.google.dagger:dagger-compiler:2.0.2'
testCompile project(path: ':briar-tests')
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.mockito:mockito-core:1.10.19'
}
@@ -62,19 +67,6 @@ dependencyVerification {
]
}
def getGitHash = { ->
def stdout = new ByteArrayOutputStream()
try {
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = stdout
}
return stdout.toString().trim()
} catch (Exception ignored) {
return "No commit hash"
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
@@ -83,7 +75,6 @@ android {
minSdkVersion 14
targetSdkVersion 22
resValue "string", "app_package", "org.briarproject.briar"
buildConfigField "String", "GitHash", "\"${getGitHash()}\""
}
buildTypes {

View File

@@ -2,9 +2,12 @@
<manifest
package="org.briarproject.briar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="13"
android:versionName="0.13">
<uses-sdk tools:overrideLibrary="android.support.v14.preference"/>
<uses-feature android:name="android.hardware.bluetooth"/>
<uses-feature android:name="android.hardware.camera" />
@@ -25,7 +28,7 @@
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:logo="@mipmap/ic_launcher_round"
android:logo="@drawable/logo"
android:theme="@style/BriarTheme">
<service
@@ -44,7 +47,7 @@
android:label="@string/crash_report_title"
android:launchMode="singleInstance"
android:process=":briar_error_handler"
android:theme="@style/BriarTheme.NoActionBar"
android:theme="@style/BriarThemeNoActionBar.Default"
android:windowSoftInputMode="stateHidden">
</activity>
@@ -67,7 +70,7 @@
<activity
android:name=".android.splash.SplashScreenActivity"
android:theme="@style/BriarTheme.NoActionBar"
android:theme="@style/BriarThemeNoActionBar.Default"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
@@ -77,14 +80,14 @@
<activity
android:name=".android.navdrawer.NavDrawerActivity"
android:theme="@style/BriarTheme.NoActionBar"
android:theme="@style/BriarThemeNoActionBar.Default"
android:launchMode="singleTop">
</activity>
<activity
android:name=".android.contact.ConversationActivity"
android:label="@string/app_name"
android:theme="@style/BriarTheme.NoActionBar"
android:theme="@style/BriarThemeNoActionBar.Default"
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
android:windowSoftInputMode="stateHidden|adjustResize">
<meta-data
@@ -108,7 +111,6 @@
android:name=".android.privategroup.conversation.GroupActivity"
android:label="@string/app_name"
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
android:theme="@style/BriarTheme.NoActionBar"
android:windowSoftInputMode="adjustResize|stateHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -192,7 +194,6 @@
android:name=".android.forum.ForumActivity"
android:label="@string/app_name"
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
android:theme="@style/BriarTheme.NoActionBar"
android:windowSoftInputMode="adjustResize|stateHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -244,11 +245,11 @@
<activity
android:name=".android.blog.BlogActivity"
android:parentActivityName=".android.navdrawer.NavDrawerActivity"
android:theme="@style/BriarTheme.NoActionBar">
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.navdrawer.NavDrawerActivity"/>
android:value=".android.navdrawer.NavDrawerActivity"
/>
</activity>
<activity
@@ -307,7 +308,7 @@
<activity
android:name=".android.keyagreement.KeyAgreementActivity"
android:label="@string/add_contact_title"
android:theme="@style/BriarTheme.NoActionBar"
android:theme="@style/BriarThemeNoActionBar.Default"
android:parentActivityName=".android.navdrawer.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -12,7 +12,6 @@ import android.os.Build;
import android.support.annotation.UiThread;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseExecutor;
@@ -328,8 +327,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} else if (settings.getBoolean("notifyPrivateMessages", true)) {
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext);
b.setSmallIcon(R.drawable.notification_private_message);
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
b.setSmallIcon(R.drawable.message_notification_icon);
b.setContentTitle(appContext.getText(R.string.app_name));
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.private_message_notification_text, contactTotal,
@@ -437,8 +435,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} else if (settings.getBoolean(PREF_NOTIFY_GROUP, true)) {
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext);
b.setSmallIcon(R.drawable.notification_private_group);
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
b.setSmallIcon(R.drawable.message_notification_icon);
b.setContentTitle(appContext.getText(R.string.app_name));
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.group_message_notification_text, groupTotal,
@@ -533,8 +530,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} else if (settings.getBoolean("notifyForumPosts", true)) {
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext);
b.setSmallIcon(R.drawable.notification_forum);
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
b.setSmallIcon(R.drawable.message_notification_icon);
b.setContentTitle(appContext.getText(R.string.app_name));
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.forum_post_notification_text, forumTotal,
@@ -629,8 +625,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} else if (settings.getBoolean(PREF_NOTIFY_BLOG, true)) {
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext);
b.setSmallIcon(R.drawable.notification_blog);
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
b.setSmallIcon(R.drawable.message_notification_icon);
b.setContentTitle(appContext.getText(R.string.app_name));
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.blog_post_notification_text, blogTotal,
@@ -690,8 +685,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
private void updateIntroductionNotification() {
NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext);
b.setSmallIcon(R.drawable.notification_introduction);
b.setColor(ContextCompat.getColor(appContext, R.color.briar_primary));
b.setSmallIcon(R.drawable.introduction_notification);
b.setContentTitle(appContext.getText(R.string.app_name));
b.setContentText(appContext.getResources().getQuantityString(
R.plurals.introduction_notification_text, introductionTotal,

View File

@@ -10,7 +10,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -76,8 +75,7 @@ public class BriarService extends Service {
}
// Show an ongoing notification that the service is running
NotificationCompat.Builder b = new NotificationCompat.Builder(this);
b.setSmallIcon(R.drawable.notification_ongoing);
b.setColor(ContextCompat.getColor(this, R.color.briar_primary));
b.setSmallIcon(R.drawable.ongoing_notification_icon);
b.setContentTitle(getText(R.string.ongoing_notification_title));
b.setContentText(getText(R.string.ongoing_notification_text));
b.setWhen(0); // Don't show the time

View File

@@ -2,12 +2,10 @@ package org.briarproject.briar.android.activity;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.UiThread;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.android.AndroidComponent;
import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.DestroyableContext;
@@ -118,10 +116,4 @@ public abstract class BaseActivity extends AppCompatActivity
Object o = getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
}
@UiThread
public void handleDbException(DbException e) {
supportFinishAfterTransition();
}
}

View File

@@ -3,19 +3,10 @@ package org.briarproject.briar.android.activity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.transition.Slide;
import android.transition.Transition;
import android.view.Gravity;
import android.view.Window;
import org.briarproject.briar.R;
import org.briarproject.briar.android.controller.BriarController;
import org.briarproject.briar.android.controller.DbController;
import org.briarproject.briar.android.controller.handler.UiResultHandler;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.login.PasswordActivity;
import org.briarproject.briar.android.panic.ExitActivity;
@@ -28,7 +19,6 @@ import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
@SuppressLint("Registered")
public abstract class BriarActivity extends BaseActivity {
@@ -37,6 +27,8 @@ public abstract class BriarActivity extends BaseActivity {
public static final String GROUP_ID = "briar.GROUP_ID";
public static final String GROUP_NAME = "briar.GROUP_NAME";
public static final int REQUEST_PASSWORD = 1;
private static final Logger LOG =
Logger.getLogger(BriarActivity.class.getName());
@@ -52,7 +44,7 @@ public abstract class BriarActivity extends BaseActivity {
super.onActivityResult(request, result, data);
if (request == REQUEST_PASSWORD) {
if (result == RESULT_OK) briarController.startAndBindService();
else supportFinishAfterTransition();
else finish();
}
}
@@ -61,62 +53,11 @@ public abstract class BriarActivity extends BaseActivity {
super.onStart();
if (!briarController.hasEncryptionKey() && !isFinishing()) {
Intent i = new Intent(this, PasswordActivity.class);
i.setFlags(FLAG_ACTIVITY_SINGLE_TOP);
i.setFlags(FLAG_ACTIVITY_NO_ANIMATION | FLAG_ACTIVITY_SINGLE_TOP);
startActivityForResult(i, REQUEST_PASSWORD);
}
}
protected void showInitialFragment(BaseFragment f) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.commit();
}
public void showNextFragment(BaseFragment f) {
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.step_next_in,
R.anim.step_previous_out, R.anim.step_previous_in,
R.anim.step_next_out)
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag())
.commit();
}
public void setSceneTransitionAnimation() {
if (Build.VERSION.SDK_INT < 21) return;
Transition slide = new Slide(Gravity.RIGHT);
slide.excludeTarget(android.R.id.statusBarBackground, true);
slide.excludeTarget(android.R.id.navigationBarBackground, true);
Window window = getWindow();
window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
window.setExitTransition(slide);
window.setEnterTransition(slide);
window.setTransitionBackgroundFadeDuration(getResources()
.getInteger(android.R.integer.config_longAnimTime));
window.setBackgroundDrawableResource(android.R.color.transparent);
}
/**
* This should be called after the content view has been added in onCreate()
*
* @param ownLayout true if the custom toolbar brings its own layout
* @return the Toolbar object or null if content view did not contain one
*/
@Nullable
protected Toolbar setUpCustomToolbar(boolean ownLayout) {
// Custom Toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayShowHomeEnabled(true);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowCustomEnabled(ownLayout);
ab.setDisplayShowTitleEnabled(!ownLayout);
}
return toolbar;
}
protected void signOut(final boolean removeFromRecentApps) {
briarController.signOut(new UiResultHandler<Void>(this) {
@Override
@@ -142,7 +83,7 @@ public abstract class BriarActivity extends BaseActivity {
private void finishAndExit() {
if (Build.VERSION.SDK_INT >= 21) finishAndRemoveTask();
else supportFinishAfterTransition();
else finish();
LOG.info("Exiting");
System.exit(0);
}
@@ -157,7 +98,7 @@ public abstract class BriarActivity extends BaseActivity {
runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
supportFinishAfterTransition();
finish();
}
});
}

View File

@@ -0,0 +1,82 @@
package org.briarproject.briar.android.activity;
import android.support.annotation.AnimRes;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.ContactListFragment;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
/**
* This class should be extended by classes that wish to utilise fragments in
* Briar, it encapsulates all fragment related code.
*/
public abstract class BriarFragmentActivity extends BriarActivity {
protected void clearBackStack() {
getSupportFragmentManager().popBackStackImmediate(null,
POP_BACK_STACK_INCLUSIVE);
}
@Override
public void onBackPressed() {
if (this instanceof NavDrawerActivity &&
getSupportFragmentManager().getBackStackEntryCount() == 0 &&
getSupportFragmentManager()
.findFragmentByTag(ContactListFragment.TAG) == null) {
/*
This Makes sure that the first fragment (ContactListFragment) the
user sees is the same as the last fragment the user sees before
exiting. This models the typical Google navigation behaviour such
as in Gmail/Inbox.
*/
startFragment(ContactListFragment.newInstance());
} else {
super.onBackPressed();
}
}
public void onFragmentCreated(String tag) {
}
protected void startFragment(BaseFragment fragment) {
if (getSupportFragmentManager().getBackStackEntryCount() == 0)
startFragment(fragment, false);
else startFragment(fragment, true);
}
protected void showMessageDialog(int titleStringId, int msgStringId) {
// TODO replace with custom dialog fragment ?
AlertDialog.Builder builder = new AlertDialog.Builder(this,
R.style.BriarDialogTheme);
builder.setTitle(titleStringId);
builder.setMessage(msgStringId);
builder.setPositiveButton(R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
public void startFragment(BaseFragment fragment,
boolean isAddedToBackStack) {
startFragment(fragment, 0, 0, isAddedToBackStack);
}
private void startFragment(BaseFragment fragment,
@AnimRes int inAnimation, @AnimRes int outAnimation,
boolean isAddedToBackStack) {
FragmentTransaction trans =
getSupportFragmentManager().beginTransaction();
if (inAnimation != 0 && outAnimation != 0) {
trans.setCustomAnimations(inAnimation, 0, 0, outAnimation);
}
trans.replace(R.id.content_fragment, fragment, fragment.getUniqueTag());
if (isAddedToBackStack) {
trans.addToBackStack(fragment.getUniqueTag());
}
trans.commit();
}
}

View File

@@ -1,14 +0,0 @@
package org.briarproject.briar.android.activity;
public interface RequestCodes {
int REQUEST_PASSWORD = 1;
int REQUEST_BLUETOOTH = 2;
int REQUEST_INTRODUCTION = 3;
int REQUEST_GROUP_INVITE = 4;
int REQUEST_SHARE_FORUM = 5;
int REQUEST_WRITE_BLOG_POST = 6;
int REQUEST_SHARE_BLOG = 7;
int REQUEST_RINGTONE = 8;
}

View File

@@ -1,8 +1,6 @@
package org.briarproject.briar.android.blog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CallSuper;
import android.support.annotation.UiThread;
import android.view.LayoutInflater;
@@ -12,7 +10,6 @@ import android.widget.ProgressBar;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.fragment.BaseFragment;
@@ -22,7 +19,7 @@ import javax.annotation.Nullable;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.briarproject.briar.android.util.UiUtils.MIN_DATE_RESOLUTION;
import static org.briarproject.briar.android.util.UiUtils.MIN_RESOLUTION;
@UiThread
@MethodsNotNullByDefault
@@ -34,9 +31,7 @@ abstract class BasePostFragment extends BaseFragment {
private static final Logger LOG =
Logger.getLogger(BasePostFragment.class.getName());
private final Handler handler = new Handler(Looper.getMainLooper());
protected MessageId postId;
private View view;
private ProgressBar progressBar;
private BlogPostViewHolder ui;
private BlogPostItem post;
@@ -48,12 +43,7 @@ abstract class BasePostFragment extends BaseFragment {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
// retrieve MessageId of blog post from arguments
byte[] p = getArguments().getByteArray(POST_ID);
if (p == null) throw new IllegalStateException("No post ID in args");
postId = new MessageId(p);
View view = inflater.inflate(R.layout.fragment_blog_post, container,
view = inflater.inflate(R.layout.fragment_blog_post, container,
false);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
progressBar.setVisibility(VISIBLE);
@@ -86,19 +76,21 @@ abstract class BasePostFragment extends BaseFragment {
refresher = new Runnable() {
@Override
public void run() {
if (ui == null) return;
LOG.info("Updating Content...");
ui.updateDate(post.getTimestamp());
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
view.postDelayed(refresher, MIN_RESOLUTION);
}
};
LOG.info("Adding Handler Callback");
handler.postDelayed(refresher, MIN_DATE_RESOLUTION);
view.postDelayed(refresher, MIN_RESOLUTION);
}
private void stopPeriodicUpdate() {
if (refresher != null) {
if (refresher != null && ui != null) {
LOG.info("Removing Handler Callback");
handler.removeCallbacks(refresher);
view.removeCallbacks(refresher);
}
}

View File

@@ -2,59 +2,43 @@ package org.briarproject.briar.android.blog;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.View;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
import javax.inject.Inject;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class BlogActivity extends BriarActivity
implements BaseFragmentListener {
public class BlogActivity extends BriarActivity implements
OnBlogPostClickListener, BaseFragmentListener {
static final int REQUEST_WRITE_POST = 1;
static final int REQUEST_SHARE = 2;
@Inject
BlogController blogController;
@Override
public void onCreate(@Nullable Bundle state) {
public void onCreate(Bundle state) {
super.onCreate(state);
// GroupId from Intent
Intent i = getIntent();
byte[] b = i.getByteArrayExtra(GROUP_ID);
if (b == null) throw new IllegalStateException("No group ID in intent");
final GroupId groupId = new GroupId(b);
GroupId groupId = new GroupId(b);
blogController.setGroupId(groupId);
setContentView(R.layout.activity_fragment_container_toolbar);
Toolbar toolbar = setUpCustomToolbar(false);
// Open Sharing Status on Toolbar click
if (toolbar != null) {
toolbar.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(BlogActivity.this,
BlogSharingStatusActivity.class);
i.putExtra(GROUP_ID, groupId.getBytes());
startActivity(i);
}
});
}
setContentView(R.layout.activity_fragment_container);
if (state == null) {
showInitialFragment(BlogFragment.newInstance(groupId));
BlogFragment f = BlogFragment.newInstance(groupId);
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.commit();
}
}
@@ -63,4 +47,16 @@ public class BlogActivity extends BriarActivity
component.inject(this);
}
@Override
public void onBlogPostClick(BlogPostItem post) {
BlogPostFragment f = BlogPostFragment.newInstance(post.getId());
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag())
.commit();
}
@Override
public void onFragmentCreated(String tag) {
}
}

View File

@@ -1,8 +1,5 @@
package org.briarproject.briar.android.blog;
import android.support.annotation.UiThread;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
@@ -16,8 +13,6 @@ public interface BlogController extends BaseController {
void setGroupId(GroupId g);
void setBlogSharingListener(BlogSharingListener listener);
void loadBlogPosts(
ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler);
@@ -28,15 +23,4 @@ public interface BlogController extends BaseController {
void deleteBlog(ResultExceptionHandler<Void, DbException> handler);
void loadSharingContacts(
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
interface BlogSharingListener extends BlogListener {
@UiThread
void onBlogInvitationAccepted(ContactId c);
@UiThread
void onBlogLeft(ContactId c);
}
}

View File

@@ -2,8 +2,6 @@ package org.briarproject.briar.android.blog;
import android.app.Activity;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
@@ -22,13 +20,8 @@ import org.briarproject.briar.android.controller.handler.ResultExceptionHandler;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.blog.BlogSharingManager;
import org.briarproject.briar.api.blog.event.BlogInvitationResponseReceivedEvent;
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
import org.briarproject.briar.api.sharing.InvitationResponse;
import org.briarproject.briar.api.sharing.event.ContactLeftShareableEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -46,19 +39,15 @@ class BlogControllerImpl extends BaseControllerImpl
private static final Logger LOG =
Logger.getLogger(BlogControllerImpl.class.getName());
private final BlogSharingManager blogSharingManager;
private volatile GroupId groupId = null;
private volatile BlogSharingListener listener;
@Inject
BlogControllerImpl(@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager, EventBus eventBus,
AndroidNotificationManager notificationManager,
IdentityManager identityManager, BlogManager blogManager,
BlogSharingManager blogSharingManager) {
IdentityManager identityManager, BlogManager blogManager) {
super(dbExecutor, lifecycleManager, eventBus, notificationManager,
identityManager, blogManager);
this.blogSharingManager = blogSharingManager;
}
@Override
@@ -87,12 +76,6 @@ class BlogControllerImpl extends BaseControllerImpl
groupId = g;
}
@Override
public void setBlogSharingListener(BlogSharingListener listener) {
super.setBlogListener(listener);
this.listener = listener;
}
@Override
public void eventOccurred(Event e) {
if (groupId == null) throw new IllegalStateException();
@@ -102,20 +85,6 @@ class BlogControllerImpl extends BaseControllerImpl
LOG.info("Blog post added");
onBlogPostAdded(b.getHeader(), b.isLocal());
}
} else if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent b =
(BlogInvitationResponseReceivedEvent) e;
InvitationResponse r = b.getResponse();
if (r.getGroupId().equals(groupId) && r.wasAccepted()) {
LOG.info("Blog invitation accepted");
onBlogInvitationAccepted(b.getContactId());
}
} else if (e instanceof ContactLeftShareableEvent) {
ContactLeftShareableEvent s = (ContactLeftShareableEvent) e;
if (s.getGroupId().equals(groupId)) {
LOG.info("Blog left by contact");
onBlogLeft(s.getContactId());
}
} else if (e instanceof GroupRemovedEvent) {
GroupRemovedEvent g = (GroupRemovedEvent) e;
if (g.getGroup().getId().equals(groupId)) {
@@ -125,24 +94,6 @@ class BlogControllerImpl extends BaseControllerImpl
}
}
private void onBlogInvitationAccepted(final ContactId c) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onBlogInvitationAccepted(c);
}
});
}
private void onBlogLeft(final ContactId c) {
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
@Override
public void run() {
listener.onBlogLeft(c);
}
});
}
@Override
public void loadBlogPosts(
final ResultExceptionHandler<Collection<BlogPostItem>, DbException> handler) {
@@ -208,27 +159,4 @@ class BlogControllerImpl extends BaseControllerImpl
});
}
@Override
public void loadSharingContacts(
final ResultExceptionHandler<Collection<ContactId>, DbException> handler) {
if (groupId == null) throw new IllegalStateException();
runOnDbThread(new Runnable() {
@Override
public void run() {
try {
Collection<Contact> contacts =
blogSharingManager.getSharedWith(groupId);
Collection<ContactId> contactIds =
new ArrayList<>(contacts.size());
for (Contact c : contacts) contactIds.add(c.getId());
handler.onResult(contactIds);
} catch (DbException e) {
if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
handler.onException(e);
}
}
});
}
}

View File

@@ -5,8 +5,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
@@ -17,7 +17,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -25,10 +24,8 @@ import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.blog.BlogController.BlogSharingListener;
import org.briarproject.briar.android.blog.BaseController.BlogListener;
import org.briarproject.briar.android.blog.BlogPostAdapter.OnBlogPostClickListener;
import org.briarproject.briar.android.controller.SharingController;
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.sharing.BlogSharingStatusActivity;
@@ -44,25 +41,22 @@ import javax.inject.Inject;
import static android.app.Activity.RESULT_OK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_BLOG;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_WRITE_BLOG_POST;
import static org.briarproject.briar.android.controller.SharingController.SharingListener;
import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_SHARE;
import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_WRITE_POST;
@UiThread
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class BlogFragment extends BaseFragment
implements BlogSharingListener, SharingListener,
OnBlogPostClickListener {
public class BlogFragment extends BaseFragment implements
BlogListener {
private final static String TAG = BlogFragment.class.getName();
@Inject
BlogController blogController;
@Inject
SharingController sharingController;
private GroupId groupId;
private BlogPostAdapter adapter;
@@ -93,7 +87,8 @@ public class BlogFragment extends BaseFragment
View v = inflater.inflate(R.layout.fragment_blog, container, false);
adapter = new BlogPostAdapter(getActivity(), this);
adapter = new BlogPostAdapter(getActivity(),
(OnBlogPostClickListener) getActivity());
list = (BriarRecyclerView) v.findViewById(R.id.postList);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
list.setAdapter(adapter);
@@ -106,16 +101,13 @@ public class BlogFragment extends BaseFragment
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
blogController.setBlogSharingListener(this);
sharingController.setSharingListener(this);
blogController.setBlogListener(this);
}
@Override
public void onStart() {
super.onStart();
sharingController.onStart();
loadBlog();
loadSharedContacts();
loadBlogPosts(false);
list.startPeriodicUpdate();
}
@@ -123,7 +115,6 @@ public class BlogFragment extends BaseFragment
@Override
public void onStop() {
super.onStop();
sharingController.onStop();
list.stopPeriodicUpdate();
}
@@ -140,25 +131,30 @@ public class BlogFragment extends BaseFragment
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
ActivityOptionsCompat options =
makeCustomAnimation(getActivity(),
android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
switch (item.getItemId()) {
case R.id.action_write_blog_post:
Intent i = new Intent(getActivity(),
WriteBlogPostActivity.class);
i.putExtra(GROUP_ID, groupId.getBytes());
startActivityForResult(i, REQUEST_WRITE_BLOG_POST);
startActivityForResult(i, REQUEST_WRITE_POST,
options.toBundle());
return true;
case R.id.action_blog_share:
Intent i2 = new Intent(getActivity(), ShareBlogActivity.class);
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
i2.putExtra(GROUP_ID, groupId.getBytes());
startActivityForResult(i2, REQUEST_SHARE_BLOG);
startActivityForResult(i2, REQUEST_SHARE, options.toBundle());
return true;
case R.id.action_blog_sharing_status:
Intent i3 = new Intent(getActivity(),
BlogSharingStatusActivity.class);
i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
i3.putExtra(GROUP_ID, groupId.getBytes());
startActivity(i3);
startActivity(i3, options.toBundle());
return true;
case R.id.action_blog_delete:
showDeleteDialog();
@@ -172,10 +168,10 @@ public class BlogFragment extends BaseFragment
public void onActivityResult(int request, int result, Intent data) {
super.onActivityResult(request, result, data);
if (request == REQUEST_WRITE_BLOG_POST && result == RESULT_OK) {
if (request == REQUEST_WRITE_POST && result == RESULT_OK) {
displaySnackbar(R.string.blogs_blog_post_created, true);
loadBlogPosts(true);
} else if (request == REQUEST_SHARE_BLOG && result == RESULT_OK) {
} else if (request == REQUEST_SHARE && result == RESULT_OK) {
displaySnackbar(R.string.blogs_sharing_snackbar, false);
}
}
@@ -205,18 +201,13 @@ public class BlogFragment extends BaseFragment
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
finish();
}
}
);
}
@Override
public void onBlogPostClick(BlogPostItem post) {
BlogPostFragment f = BlogPostFragment.newInstance(post.getId());
showNextFragment(f);
}
private void loadBlogPosts(final boolean reload) {
blogController.loadBlogPosts(
new UiResultExceptionHandler<Collection<BlogPostItem>, DbException>(
@@ -233,7 +224,8 @@ public class BlogFragment extends BaseFragment
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
finish();
}
});
}
@@ -252,7 +244,8 @@ public class BlogFragment extends BaseFragment
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
finish();
}
});
}
@@ -262,51 +255,6 @@ public class BlogFragment extends BaseFragment
getActivity().setTitle(title);
}
private void loadSharedContacts() {
blogController.loadSharingContacts(
new UiResultExceptionHandler<Collection<ContactId>, DbException>(this) {
@Override
public void onResultUi(Collection<ContactId> contacts) {
sharingController.addAll(contacts);
int online = sharingController.getOnlineCount();
setToolbarSubTitle(contacts.size(), online);
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
}
});
}
@Override
public void onBlogInvitationAccepted(ContactId c) {
sharingController.add(c);
setToolbarSubTitle(sharingController.getTotalCount(),
sharingController.getOnlineCount());
}
@Override
public void onBlogLeft(ContactId c) {
sharingController.remove(c);
setToolbarSubTitle(sharingController.getTotalCount(),
sharingController.getOnlineCount());
}
@Override
public void onSharingInfoUpdated(int total, int online) {
setToolbarSubTitle(total, online);
}
private void setToolbarSubTitle(int total, int online) {
ActionBar actionBar =
((BriarActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
actionBar.setSubtitle(
getString(R.string.shared_with, total, online));
}
}
private void showWriteButton() {
isMyBlog = true;
if (writeButton != null)
@@ -369,7 +317,8 @@ public class BlogFragment extends BaseFragment
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
finish();
}
});
}
@@ -378,5 +327,4 @@ public class BlogFragment extends BaseFragment
public void onBlogRemoved() {
finish();
}
}

View File

@@ -2,8 +2,6 @@ package org.briarproject.briar.android.blog;
import org.briarproject.briar.android.activity.ActivityScope;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.controller.SharingController;
import org.briarproject.briar.android.controller.SharingControllerImpl;
import dagger.Module;
import dagger.Provides;
@@ -24,12 +22,4 @@ public class BlogModule {
FeedController provideFeedController(FeedControllerImpl feedController) {
return feedController;
}
@ActivityScope
@Provides
SharingController provideSharingController(
SharingControllerImpl sharingController) {
return sharingController;
}
}

View File

@@ -2,6 +2,9 @@ package org.briarproject.briar.android.blog;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -10,6 +13,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.controller.handler.UiResultExceptionHandler;
import javax.annotation.Nullable;
import javax.inject.Inject;
@UiThread
@@ -19,6 +23,8 @@ public class BlogPostFragment extends BasePostFragment {
private static final String TAG = BlogPostFragment.class.getName();
private MessageId postId;
@Inject
BlogController blogController;
@@ -32,6 +38,20 @@ public class BlogPostFragment extends BasePostFragment {
return f;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
Bundle args = getArguments();
byte[] p = args.getByteArray(POST_ID);
if (p == null) throw new IllegalStateException("No post ID in args");
postId = new MessageId(p);
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public String getUniqueTag() {
return TAG;
@@ -55,7 +75,8 @@ public class BlogPostFragment extends BasePostFragment {
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
finish();
}
});
}

View File

@@ -137,14 +137,15 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
i.putExtra(GROUP_ID, item.getGroupId().getBytes());
i.putExtra(POST_ID, item.getId().getBytes());
// work-around for android bug #224270
if (Build.VERSION.SDK_INT >= 23) {
ActivityOptionsCompat options =
makeSceneTransitionAnimation((Activity) ctx, layout,
getTransitionName(item.getId()));
ActivityCompat.startActivity((Activity) ctx, i,
options.toBundle());
ActivityCompat
.startActivity((Activity) ctx, i,
options.toBundle());
} else {
// work-around for android bug #224270
ctx.startActivity(i);
}
}
@@ -166,7 +167,6 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
reblogger.setDate(item.getTimestamp());
reblogger.setBlogLink(item.getGroupId());
reblogger.setVisibility(VISIBLE);
reblogger.setPersona(AuthorView.REBLOGGER);
author.setPersona(AuthorView.COMMENTER);

View File

@@ -4,6 +4,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater;
@@ -35,8 +36,9 @@ import javax.inject.Inject;
import static android.app.Activity.RESULT_OK;
import static android.support.design.widget.Snackbar.LENGTH_LONG;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_WRITE_BLOG_POST;
import static org.briarproject.briar.android.blog.BlogActivity.REQUEST_WRITE_POST;
@UiThread
@MethodsNotNullByDefault
@@ -70,8 +72,6 @@ public class FeedFragment extends BaseFragment implements
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(R.string.blogs_button);
View v = inflater.inflate(R.layout.fragment_blog, container, false);
adapter = new BlogPostAdapter(getActivity(), this);
@@ -96,7 +96,7 @@ public class FeedFragment extends BaseFragment implements
super.onActivityResult(requestCode, resultCode, data);
// The BlogPostAddedEvent arrives when the controller is not listening
if (requestCode == REQUEST_WRITE_BLOG_POST && resultCode == RESULT_OK) {
if (requestCode == REQUEST_WRITE_POST && resultCode == RESULT_OK) {
showSnackBar(R.string.blogs_blog_post_created);
}
}
@@ -105,7 +105,6 @@ public class FeedFragment extends BaseFragment implements
public void onStart() {
super.onStart();
feedController.onStart();
list.startPeriodicUpdate();
loadPersonalBlog();
loadBlogPosts(false);
}
@@ -130,7 +129,7 @@ public class FeedFragment extends BaseFragment implements
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
}
});
}
@@ -154,10 +153,11 @@ public class FeedFragment extends BaseFragment implements
}
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
public void onExceptionUi(DbException e) {
// TODO: Decide how to handle errors in the UI
}
});
list.startPeriodicUpdate();
}
@Override
@@ -169,24 +169,28 @@ public class FeedFragment extends BaseFragment implements
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (personalBlog == null) return false;
ActivityOptionsCompat options =
makeCustomAnimation(getActivity(), android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
switch (item.getItemId()) {
case R.id.action_write_blog_post:
Intent i1 =
new Intent(getActivity(), WriteBlogPostActivity.class);
i1.putExtra(GROUP_ID, personalBlog.getId().getBytes());
startActivityForResult(i1, REQUEST_WRITE_BLOG_POST);
startActivityForResult(i1, REQUEST_WRITE_POST,
options.toBundle());
return true;
case R.id.action_rss_feeds_import:
Intent i2 =
new Intent(getActivity(), RssFeedImportActivity.class);
i2.putExtra(GROUP_ID, personalBlog.getId().getBytes());
startActivity(i2);
startActivity(i2, options.toBundle());
return true;
case R.id.action_rss_feeds_manage:
Intent i3 =
new Intent(getActivity(), RssFeedManageActivity.class);
i3.putExtra(GROUP_ID, personalBlog.getId().getBytes());
startActivity(i3);
startActivity(i3, options.toBundle());
return true;
default:
return super.onOptionsItemSelected(item);
@@ -211,7 +215,7 @@ public class FeedFragment extends BaseFragment implements
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
}
}
);
@@ -221,7 +225,10 @@ public class FeedFragment extends BaseFragment implements
public void onBlogPostClick(BlogPostItem post) {
FeedPostFragment f =
FeedPostFragment.newInstance(post.getGroupId(), post.getId());
showNextFragment(f);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.content_fragment, f, f.getUniqueTag())
.addToBackStack(f.getUniqueTag())
.commit();
}
@Override
@@ -262,5 +269,4 @@ public class FeedFragment extends BaseFragment implements
public void onBlogRemoved() {
loadBlogPosts(true);
}
}

View File

@@ -26,6 +26,7 @@ public class FeedPostFragment extends BasePostFragment {
private static final String TAG = FeedPostFragment.class.getName();
private MessageId postId;
private GroupId blogId;
@Inject
@@ -53,6 +54,10 @@ public class FeedPostFragment extends BasePostFragment {
if (b == null) throw new IllegalStateException("No group ID in args");
blogId = new GroupId(b);
byte[] p = args.getByteArray(POST_ID);
if (p == null) throw new IllegalStateException("No post ID in args");
postId = new MessageId(p);
return super.onCreateView(inflater, container, savedInstanceState);
}
@@ -79,7 +84,7 @@ public class FeedPostFragment extends BasePostFragment {
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO: Decide how to handle errors in the UI
}
});
}

View File

@@ -1,7 +1,11 @@
package org.briarproject.briar.android.blog;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.transition.Fade;
import android.transition.Transition;
import android.view.MenuItem;
import org.briarproject.bramble.api.sync.GroupId;
@@ -19,7 +23,10 @@ public class ReblogActivity extends BriarActivity implements
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSceneTransitionAnimation();
if (Build.VERSION.SDK_INT >= 21) {
setTransition();
}
Intent intent = getIntent();
byte[] groupId = intent.getByteArrayExtra(GROUP_ID);
@@ -34,7 +41,10 @@ public class ReblogActivity extends BriarActivity implements
if (savedInstanceState == null) {
ReblogFragment f = ReblogFragment
.newInstance(new GroupId(groupId), new MessageId(postId));
showInitialFragment(f);
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fragmentContainer, f)
.commit();
}
}
@@ -54,4 +64,18 @@ public class ReblogActivity extends BriarActivity implements
component.inject(this);
}
@Override
public void onFragmentCreated(String tag) {
}
@TargetApi(21)
private void setTransition() {
Transition fade = new Fade();
fade.excludeTarget(android.R.id.statusBarBackground, true);
fade.excludeTarget(R.id.action_bar_container, true);
fade.excludeTarget(android.R.id.navigationBarBackground, true);
getWindow().setExitTransition(fade);
getWindow().setEnterTransition(fade);
}
}

View File

@@ -74,7 +74,8 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
blogId = new GroupId(args.getByteArray(GROUP_ID));
postId = new MessageId(args.getByteArray(POST_ID));
View v = inflater.inflate(R.layout.fragment_reblog, container, false);
View v = inflater.inflate(R.layout.fragment_reblog, container,
false);
ui = new ViewHolder(v);
ui.post.setTransitionName(postId);
ui.input.setSendButtonEnabled(false);
@@ -99,7 +100,8 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO
finish();
}
});
}
@@ -129,7 +131,8 @@ public class ReblogFragment extends BaseFragment implements TextInputListener {
new UiExceptionHandler<DbException>(this) {
@Override
public void onExceptionUi(DbException exception) {
handleDbException(exception);
// TODO proper error handling
// do nothing, this fragment is gone already
}
});
finish();

View File

@@ -3,6 +3,8 @@ package org.briarproject.briar.android.blog;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.view.Menu;
import android.view.MenuInflater;
@@ -24,6 +26,7 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static android.support.design.widget.Snackbar.LENGTH_LONG;
import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
import static java.util.logging.Level.WARNING;
public class RssFeedManageActivity extends BriarActivity
@@ -86,9 +89,13 @@ public class RssFeedManageActivity extends BriarActivity
onBackPressed();
return true;
case R.id.action_rss_feeds_import:
Intent i = new Intent(this, RssFeedImportActivity.class);
Intent i =
new Intent(this, RssFeedImportActivity.class);
i.putExtra(GROUP_ID, groupId.getBytes());
startActivity(i);
ActivityOptionsCompat options =
makeCustomAnimation(this, android.R.anim.slide_in_left,
android.R.anim.slide_out_right);
ActivityCompat.startActivity(this, i, options.toBundle());
return true;
default:
return super.onOptionsItemSelected(item);

View File

@@ -10,27 +10,13 @@ import javax.annotation.concurrent.NotThreadSafe;
public class ContactItem {
private final Contact contact;
private boolean connected;
public ContactItem(Contact contact) {
this(contact, false);
}
public ContactItem(Contact contact, boolean connected) {
this.contact = contact;
this.connected = connected;
}
public Contact getContact() {
return contact;
}
boolean isConnected() {
return connected;
}
void setConnected(boolean connected) {
this.connected = connected;
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.contact;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v7.widget.RecyclerView;
import android.view.View;
@@ -13,6 +12,8 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
import javax.annotation.Nullable;
import im.delight.android.identicons.IdenticonDrawable;
@UiThread
@@ -23,8 +24,6 @@ public class ContactItemViewHolder<I extends ContactItem>
protected final ViewGroup layout;
protected final ImageView avatar;
protected final TextView name;
@Nullable
protected final ImageView bulb;
public ContactItemViewHolder(View v) {
super(v);
@@ -32,8 +31,6 @@ public class ContactItemViewHolder<I extends ContactItem>
layout = (ViewGroup) v;
avatar = (ImageView) v.findViewById(R.id.avatarView);
name = (TextView) v.findViewById(R.id.nameView);
// this can be null as not all layouts that use this ViewHolder have it
bulb = (ImageView) v.findViewById(R.id.bulbView);
}
protected void bind(final I item,
@@ -44,15 +41,6 @@ public class ContactItemViewHolder<I extends ContactItem>
String contactName = author.getName();
name.setText(contactName);
if (bulb != null) {
// online/offline
if (item.isConnected()) {
bulb.setImageResource(R.drawable.contact_connected);
} else {
bulb.setImageResource(R.drawable.contact_disconnected);
}
}
layout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

View File

@@ -109,8 +109,6 @@ public class ContactListFragment extends BaseFragment implements EventListener {
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(R.string.contact_list_button);
View contentView = inflater.inflate(R.layout.list, container, false);
OnContactClickListener<ContactListItem> onContactClickListener =
@@ -122,6 +120,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
ContactId contactId = item.getContact().getId();
i.putExtra(CONTACT_ID, contactId.getInt());
// work-around for android bug #224270
if (Build.VERSION.SDK_INT >= 23) {
ContactListItemViewHolder holder =
(ContactListItemViewHolder) list
@@ -141,8 +140,7 @@ public class ContactListFragment extends BaseFragment implements EventListener {
ActivityCompat.startActivity(getActivity(), i,
options.toBundle());
} else {
// work-around for android bug #224270
startActivity(i);
getActivity().startActivity(i);
}
}
};

View File

@@ -10,13 +10,14 @@ import javax.annotation.concurrent.NotThreadSafe;
@NotNullByDefault
public class ContactListItem extends ContactItem {
private boolean empty;
private boolean connected, empty;
private long timestamp;
private int unread;
public ContactListItem(Contact contact, boolean connected,
GroupCount count) {
super(contact, connected);
super(contact);
this.connected = connected;
this.empty = count.getMsgCount() == 0;
this.unread = count.getUnreadCount();
this.timestamp = count.getLatestMsgTime();
@@ -29,6 +30,14 @@ public class ContactListItem extends ContactItem {
unread++;
}
boolean isConnected() {
return connected;
}
void setConnected(boolean connected) {
this.connected = connected;
}
boolean isEmpty() {
return empty;
}

Some files were not shown because too many files have changed in this diff Show More