mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Fixed race condition when closing redundant sockets.
When more than one invitation socket is opened, Alice should pick which one to use and Bob should use whichever one Alice picks. This fixes a race condition where each party picked a different socket and closed the other.
This commit is contained in:
@@ -1,111 +0,0 @@
|
||||
package org.briarproject.plugins;
|
||||
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.briarproject.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
|
||||
|
||||
public abstract class DuplexClientTest extends DuplexTest {
|
||||
|
||||
protected ClientCallback callback = null;
|
||||
|
||||
protected void run() throws IOException {
|
||||
assert plugin != null;
|
||||
// Start the plugin
|
||||
System.out.println("Starting plugin");
|
||||
if (!plugin.start()) {
|
||||
System.out.println("Plugin failed to start");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Try to connect to the server
|
||||
System.out.println("Creating connection");
|
||||
DuplexTransportConnection d = plugin.createConnection(contactId);
|
||||
if (d == null) {
|
||||
System.out.println("Connection failed");
|
||||
return;
|
||||
} else {
|
||||
System.out.println("Connection created");
|
||||
receiveChallengeSendResponse(d);
|
||||
}
|
||||
if (!plugin.supportsInvitations()) {
|
||||
System.out.println("Skipping invitation test");
|
||||
return;
|
||||
}
|
||||
// Try to create an invitation connection
|
||||
System.out.println("Creating invitation connection");
|
||||
PseudoRandom r = getPseudoRandom(123);
|
||||
d = plugin.createInvitationConnection(r, CONNECTION_TIMEOUT);
|
||||
if (d == null) {
|
||||
System.out.println("Connection failed");
|
||||
} else {
|
||||
System.out.println("Connection created");
|
||||
sendChallengeReceiveResponse(d);
|
||||
}
|
||||
} finally {
|
||||
// Stop the plugin
|
||||
System.out.println("Stopping plugin");
|
||||
plugin.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ClientCallback implements DuplexPluginCallback {
|
||||
|
||||
private Settings settings = null;
|
||||
private TransportProperties local = null;
|
||||
private Map<ContactId, TransportProperties> remote = null;
|
||||
|
||||
public ClientCallback(Settings settings, TransportProperties local,
|
||||
Map<ContactId, TransportProperties> remote) {
|
||||
this.settings = settings;
|
||||
this.local = local;
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public TransportProperties getLocalProperties() {
|
||||
return local;
|
||||
}
|
||||
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public void mergeSettings(Settings s) {
|
||||
settings = s;
|
||||
}
|
||||
|
||||
public void mergeLocalProperties(TransportProperties p) {
|
||||
local = p;
|
||||
}
|
||||
|
||||
public int showChoice(String[] options, String... message) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean showConfirmationMessage(String... message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void showMessage(String... message) {}
|
||||
|
||||
public void incomingConnectionCreated(DuplexTransportConnection d) {}
|
||||
|
||||
public void outgoingConnectionCreated(ContactId contactId,
|
||||
DuplexTransportConnection d) {}
|
||||
|
||||
public void transportEnabled() {}
|
||||
|
||||
public void transportDisabled() {}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
package org.briarproject.plugins;
|
||||
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.api.properties.TransportProperties;
|
||||
import org.briarproject.api.settings.Settings;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.briarproject.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
|
||||
|
||||
public abstract class DuplexServerTest extends DuplexTest {
|
||||
|
||||
protected ServerCallback callback = null;
|
||||
|
||||
protected void run() throws Exception {
|
||||
assert callback != null;
|
||||
assert plugin != null;
|
||||
// Start the plugin
|
||||
System.out.println("Starting plugin");
|
||||
if (!plugin.start()) {
|
||||
System.out.println("Plugin failed to start");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Wait for a connection
|
||||
System.out.println("Waiting for connection");
|
||||
if (!callback.latch.await(120, SECONDS)) {
|
||||
System.out.println("No connection received");
|
||||
return;
|
||||
}
|
||||
if (!plugin.supportsInvitations()) {
|
||||
System.out.println("Skipping invitation test");
|
||||
return;
|
||||
}
|
||||
// Try to create an invitation connection
|
||||
System.out.println("Creating invitation connection");
|
||||
DuplexTransportConnection d = plugin.createInvitationConnection(
|
||||
getPseudoRandom(123), CONNECTION_TIMEOUT);
|
||||
if (d == null) {
|
||||
System.out.println("Connection failed");
|
||||
} else {
|
||||
System.out.println("Connection created");
|
||||
receiveChallengeSendResponse(d);
|
||||
}
|
||||
} finally {
|
||||
// Stop the plugin
|
||||
System.out.println("Stopping plugin");
|
||||
plugin.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected class ServerCallback implements DuplexPluginCallback {
|
||||
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
private Settings settings;
|
||||
private TransportProperties local;
|
||||
private Map<ContactId, TransportProperties> remote;
|
||||
|
||||
public ServerCallback(Settings settings, TransportProperties local,
|
||||
Map<ContactId, TransportProperties> remote) {
|
||||
this.settings = settings;
|
||||
this.local = local;
|
||||
this.remote = remote;
|
||||
}
|
||||
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public TransportProperties getLocalProperties() {
|
||||
return local;
|
||||
}
|
||||
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public void mergeSettings(Settings s) {
|
||||
settings = s;
|
||||
}
|
||||
|
||||
public void mergeLocalProperties(TransportProperties p) {
|
||||
local = p;
|
||||
}
|
||||
|
||||
public int showChoice(String[] options, String... message) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean showConfirmationMessage(String... message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void showMessage(String... message) {}
|
||||
|
||||
public void incomingConnectionCreated(DuplexTransportConnection d) {
|
||||
System.out.println("Connection received");
|
||||
sendChallengeReceiveResponse(d);
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public void outgoingConnectionCreated(ContactId c,
|
||||
DuplexTransportConnection d) {}
|
||||
|
||||
public void transportEnabled() {}
|
||||
|
||||
public void transportDisabled() {}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package org.briarproject.plugins;
|
||||
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
import org.briarproject.api.plugins.TransportConnectionReader;
|
||||
import org.briarproject.api.plugins.TransportConnectionWriter;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
|
||||
abstract class DuplexTest {
|
||||
|
||||
protected static final String CHALLENGE = "Carrots!";
|
||||
protected static final String RESPONSE = "Potatoes!";
|
||||
|
||||
protected final ContactId contactId = new ContactId(234);
|
||||
|
||||
protected DuplexPlugin plugin = null;
|
||||
|
||||
protected void sendChallengeReceiveResponse(DuplexTransportConnection d) {
|
||||
assert plugin != null;
|
||||
TransportConnectionReader r = d.getReader();
|
||||
TransportConnectionWriter w = d.getWriter();
|
||||
try {
|
||||
PrintStream out = new PrintStream(w.getOutputStream());
|
||||
out.println(CHALLENGE);
|
||||
out.flush();
|
||||
System.out.println("Sent challenge: " + CHALLENGE);
|
||||
Scanner in = new Scanner(r.getInputStream());
|
||||
if (in.hasNextLine()) {
|
||||
String response = in.nextLine();
|
||||
System.out.println("Received response: " + response);
|
||||
if (RESPONSE.equals(response)) {
|
||||
System.out.println("Correct response");
|
||||
} else {
|
||||
System.out.println("Incorrect response");
|
||||
}
|
||||
} else {
|
||||
System.out.println("No response");
|
||||
}
|
||||
r.dispose(false, true);
|
||||
w.dispose(false);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
r.dispose(true, true);
|
||||
w.dispose(true);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void receiveChallengeSendResponse(DuplexTransportConnection d) {
|
||||
assert plugin != null;
|
||||
TransportConnectionReader r = d.getReader();
|
||||
TransportConnectionWriter w = d.getWriter();
|
||||
try {
|
||||
Scanner in = new Scanner(r.getInputStream());
|
||||
if (in.hasNextLine()) {
|
||||
String challenge = in.nextLine();
|
||||
System.out.println("Received challenge: " + challenge);
|
||||
if (CHALLENGE.equals(challenge)) {
|
||||
|
||||
PrintStream out = new PrintStream(w.getOutputStream());
|
||||
out.println(RESPONSE);
|
||||
out.flush();
|
||||
System.out.println("Sent response: " + RESPONSE);
|
||||
} else {
|
||||
System.out.println("Incorrect challenge");
|
||||
}
|
||||
} else {
|
||||
System.out.println("No challenge");
|
||||
}
|
||||
r.dispose(false, true);
|
||||
w.dispose(false);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
r.dispose(true, true);
|
||||
w.dispose(true);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected PseudoRandom getPseudoRandom(int seed) {
|
||||
final Random random = new Random(seed);
|
||||
return new PseudoRandom() {
|
||||
public byte[] nextBytes(int bytes) {
|
||||
byte[] b = new byte[bytes];
|
||||
random.nextBytes(b);
|
||||
return b;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user