Protocol Buffers will be used for the wire protocol. As a quick test it's now used to serialize transport details when creating an invitation.

This commit is contained in:
akwizgran
2011-07-07 22:10:02 +01:00
parent 7fb589075d
commit 4deb52478d
11 changed files with 1212 additions and 17 deletions

View File

@@ -15,5 +15,6 @@
<classpathentry kind="lib" path="lib/test/hamcrest-core-1.1.jar"/> <classpathentry kind="lib" path="lib/test/hamcrest-core-1.1.jar"/>
<classpathentry kind="lib" path="lib/test/hamcrest-library-1.1.jar"/> <classpathentry kind="lib" path="lib/test/hamcrest-library-1.1.jar"/>
<classpathentry kind="lib" path="lib/test/jmock-2.5.1.jar"/> <classpathentry kind="lib" path="lib/test/jmock-2.5.1.jar"/>
<classpathentry kind="lib" path="lib/protobuf.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -59,6 +59,9 @@ public interface DatabaseComponent {
/** Returns the set of groups to which the user subscribes. */ /** Returns the set of groups to which the user subscribes. */
Set<GroupId> getSubscriptions() throws DbException; Set<GroupId> getSubscriptions() throws DbException;
/** Returns the local transport details. */
Map<String, String> getTransports() throws DbException;
/** Returns the transport details for the given contact. */ /** Returns the transport details for the given contact. */
Map<String, String> getTransports(ContactId c) throws DbException; Map<String, String> getTransports(ContactId c) throws DbException;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
package protocol;
option java_package = "net.sf.briar.api.protocol";
message TransportDetails {
message TransportDetail {
required string key = 1;
optional string value = 2;
}
repeated TransportDetail details = 1;
}

View File

@@ -1062,6 +1062,7 @@ abstract class JdbcDatabase implements Database<Connection> {
+ " WHERE contactSubscriptions.contactId = ?" + " WHERE contactSubscriptions.contactId = ?"
+ " AND statuses.contactId = ? AND status = ?" + " AND statuses.contactId = ? AND status = ?"
+ " AND sendability > ZERO()"; + " AND sendability > ZERO()";
// FIXME: Investigate the performance impact of "ORDER BY timestamp"
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
ps.setInt(2, c.getInt()); ps.setInt(2, c.getInt());

View File

@@ -393,6 +393,23 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
} }
} }
public Map<String, String> getTransports() throws DbException {
transportLock.readLock().lock();
try {
Txn txn = db.startTransaction();
try {
Map<String, String> transports = db.getTransports(txn);
db.commitTransaction(txn);
return transports;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
} finally {
transportLock.readLock().unlock();
}
}
public Map<String, String> getTransports(ContactId c) throws DbException { public Map<String, String> getTransports(ContactId c) throws DbException {
contactLock.readLock().lock(); contactLock.readLock().lock();
try { try {

View File

@@ -296,6 +296,20 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
} }
} }
public Map<String, String> getTransports() throws DbException {
synchronized(transportLock) {
Txn txn = db.startTransaction();
try {
Map<String, String> transports = db.getTransports(txn);
db.commitTransaction(txn);
return transports;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;
}
}
}
public Map<String, String> getTransports(ContactId c) throws DbException { public Map<String, String> getTransports(ContactId c) throws DbException {
synchronized(contactLock) { synchronized(contactLock) {
if(!containsContact(c)) throw new NoSuchContactException(); if(!containsContact(c)) throw new NoSuchContactException();

View File

@@ -6,21 +6,29 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Map;
import java.util.Map.Entry;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.invitation.InvitationCallback; import net.sf.briar.api.invitation.InvitationCallback;
import net.sf.briar.api.invitation.InvitationParameters; import net.sf.briar.api.invitation.InvitationParameters;
import net.sf.briar.api.protocol.Transport.TransportDetails;
import net.sf.briar.api.protocol.Transport.TransportDetails.TransportDetail;
import net.sf.briar.util.FileUtils; import net.sf.briar.util.FileUtils;
class InvitationWorker implements Runnable { class InvitationWorker implements Runnable {
private final InvitationCallback callback; private final InvitationCallback callback;
private final InvitationParameters parameters; private final InvitationParameters parameters;
private final DatabaseComponent databaseComponent;
InvitationWorker(final InvitationCallback callback, InvitationWorker(final InvitationCallback callback,
InvitationParameters parameters) { InvitationParameters parameters,
DatabaseComponent databaseComponent) {
this.callback = callback; this.callback = callback;
this.parameters = parameters; this.parameters = parameters;
this.databaseComponent = databaseComponent;
} }
public void run() { public void run() {
@@ -60,16 +68,25 @@ class InvitationWorker implements Runnable {
File invitationDat = new File(dir, "invitation.dat"); File invitationDat = new File(dir, "invitation.dat");
callback.encryptingFile(invitationDat); callback.encryptingFile(invitationDat);
// FIXME: Create a real invitation // FIXME: Create a real invitation
Map<String, String> transports;
try { try {
Thread.sleep(2000); transports = databaseComponent.getTransports();
} catch(InterruptedException ignored) {} } catch(DbException e) {
Arrays.fill(password, (char) 0); throw new IOException(e);
}
TransportDetails.Builder b = TransportDetails.newBuilder();
for(Entry<String, String> e : transports.entrySet()) {
TransportDetail.Builder b1 = TransportDetail.newBuilder();
b1.setKey(e.getKey());
b1.setValue(e.getValue());
b.addDetails(b1.build());
}
TransportDetails t = b.build();
FileOutputStream out = new FileOutputStream(invitationDat); FileOutputStream out = new FileOutputStream(invitationDat);
byte[] buf = new byte[1024]; t.writeTo(out);
new Random().nextBytes(buf);
out.write(buf, 0, buf.length);
out.flush(); out.flush();
out.close(); out.close();
Arrays.fill(password, (char) 0);
return invitationDat; return invitationDat;
} }

View File

@@ -1,13 +1,23 @@
package net.sf.briar.invitation; package net.sf.briar.invitation;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.invitation.InvitationCallback; import net.sf.briar.api.invitation.InvitationCallback;
import net.sf.briar.api.invitation.InvitationParameters; import net.sf.briar.api.invitation.InvitationParameters;
import net.sf.briar.api.invitation.InvitationWorkerFactory; import net.sf.briar.api.invitation.InvitationWorkerFactory;
import com.google.inject.Inject;
class InvitationWorkerFactoryImpl implements InvitationWorkerFactory { class InvitationWorkerFactoryImpl implements InvitationWorkerFactory {
private final DatabaseComponent databaseComponent;
@Inject
InvitationWorkerFactoryImpl(DatabaseComponent databaseComponent) {
this.databaseComponent = databaseComponent;
}
public Runnable createWorker(InvitationCallback callback, public Runnable createWorker(InvitationCallback callback,
InvitationParameters parameters) { InvitationParameters parameters) {
return new InvitationWorker(callback, parameters); return new InvitationWorker(callback, parameters, databaseComponent);
} }
} }

BIN
lib/protobuf.jar Normal file

Binary file not shown.

View File

@@ -3,10 +3,13 @@ package net.sf.briar.invitation;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
import net.sf.briar.TestUtils; import net.sf.briar.TestUtils;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.invitation.InvitationCallback; import net.sf.briar.api.invitation.InvitationCallback;
import net.sf.briar.api.invitation.InvitationParameters; import net.sf.briar.api.invitation.InvitationParameters;
@@ -33,13 +36,15 @@ public class InvitationWorkerTest extends TestCase {
context.mock(InvitationCallback.class); context.mock(InvitationCallback.class);
final InvitationParameters params = final InvitationParameters params =
context.mock(InvitationParameters.class); context.mock(InvitationParameters.class);
final DatabaseComponent database =
context.mock(DatabaseComponent.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(params).getChosenLocation(); oneOf(params).getChosenLocation();
will(returnValue(nonExistent)); will(returnValue(nonExistent));
oneOf(callback).notFound(nonExistent); oneOf(callback).notFound(nonExistent);
}}); }});
new InvitationWorker(callback, params).run(); new InvitationWorker(callback, params, database).run();
context.assertIsSatisfied(); context.assertIsSatisfied();
File[] children = testDir.listFiles(); File[] children = testDir.listFiles();
@@ -57,13 +62,15 @@ public class InvitationWorkerTest extends TestCase {
context.mock(InvitationCallback.class); context.mock(InvitationCallback.class);
final InvitationParameters params = final InvitationParameters params =
context.mock(InvitationParameters.class); context.mock(InvitationParameters.class);
final DatabaseComponent database =
context.mock(DatabaseComponent.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(params).getChosenLocation(); oneOf(params).getChosenLocation();
will(returnValue(exists)); will(returnValue(exists));
oneOf(callback).notDirectory(exists); oneOf(callback).notDirectory(exists);
}}); }});
new InvitationWorker(callback, params).run(); new InvitationWorker(callback, params, database).run();
context.assertIsSatisfied(); context.assertIsSatisfied();
File[] children = testDir.listFiles(); File[] children = testDir.listFiles();
@@ -73,27 +80,27 @@ public class InvitationWorkerTest extends TestCase {
} }
@Test @Test
public void testCreatesExe() throws IOException { public void testCreatesExe() throws IOException, DbException {
testInstallerCreation(true, false); testInstallerCreation(true, false);
} }
@Test @Test
public void testCreatesJar() throws IOException { public void testCreatesJar() throws IOException, DbException {
testInstallerCreation(false, true); testInstallerCreation(false, true);
} }
@Test @Test
public void testCreatesBoth() throws IOException { public void testCreatesBoth() throws IOException, DbException {
testInstallerCreation(true, true); testInstallerCreation(true, true);
} }
@Test @Test
public void testCreatesNeither() throws IOException { public void testCreatesNeither() throws IOException, DbException {
testInstallerCreation(false, false); testInstallerCreation(false, false);
} }
private void testInstallerCreation(final boolean createExe, private void testInstallerCreation(final boolean createExe,
final boolean createJar) throws IOException { final boolean createJar) throws IOException, DbException {
final File setup = new File(testDir, "setup.dat"); final File setup = new File(testDir, "setup.dat");
TestUtils.createFile(setup, "foo bar baz"); TestUtils.createFile(setup, "foo bar baz");
final File invitation = new File(testDir, "invitation.dat"); final File invitation = new File(testDir, "invitation.dat");
@@ -112,6 +119,8 @@ public class InvitationWorkerTest extends TestCase {
context.mock(InvitationCallback.class); context.mock(InvitationCallback.class);
final InvitationParameters params = final InvitationParameters params =
context.mock(InvitationParameters.class); context.mock(InvitationParameters.class);
final DatabaseComponent database =
context.mock(DatabaseComponent.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(params).getChosenLocation(); oneOf(params).getChosenLocation();
will(returnValue(testDir)); will(returnValue(testDir));
@@ -120,6 +129,8 @@ public class InvitationWorkerTest extends TestCase {
oneOf(params).getPassword(); oneOf(params).getPassword();
will(returnValue(new char[] {'x', 'y', 'z', 'z', 'y'})); will(returnValue(new char[] {'x', 'y', 'z', 'z', 'y'}));
oneOf(callback).encryptingFile(invitation); oneOf(callback).encryptingFile(invitation);
oneOf(database).getTransports();
will(returnValue(Collections.singletonMap("foo", "bar")));
oneOf(params).shouldCreateExe(); oneOf(params).shouldCreateExe();
will(returnValue(createExe)); will(returnValue(createExe));
oneOf(params).shouldCreateJar(); oneOf(params).shouldCreateJar();
@@ -137,7 +148,7 @@ public class InvitationWorkerTest extends TestCase {
oneOf(callback).created(expectedFiles); oneOf(callback).created(expectedFiles);
}}); }});
new InvitationWorker(callback, params).run(); new InvitationWorker(callback, params, database).run();
assertTrue(invitation.exists()); assertTrue(invitation.exists());
assertEquals(createExe, exe.exists()); assertEquals(createExe, exe.exists());