mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
Provide earlier feedback in the UI when connecting to a new contact.
Partially addresses issue #3611924.
This commit is contained in:
@@ -57,7 +57,7 @@ implements InvitationListener {
|
|||||||
private BluetoothWifiStateReceiver receiver = null;
|
private BluetoothWifiStateReceiver receiver = null;
|
||||||
private int localInvitationCode = -1, remoteInvitationCode = -1;
|
private int localInvitationCode = -1, remoteInvitationCode = -1;
|
||||||
private int localConfirmationCode = -1, remoteConfirmationCode = -1;
|
private int localConfirmationCode = -1, remoteConfirmationCode = -1;
|
||||||
private boolean connectionFailed = false;
|
private boolean connected = false, connectionFailed = false;
|
||||||
private boolean localCompared = false, remoteCompared = false;
|
private boolean localCompared = false, remoteCompared = false;
|
||||||
private boolean localMatched = false, remoteMatched = false;
|
private boolean localMatched = false, remoteMatched = false;
|
||||||
private String contactName = null;
|
private String contactName = null;
|
||||||
@@ -109,6 +109,7 @@ implements InvitationListener {
|
|||||||
remoteInvitationCode = s.getRemoteInvitationCode();
|
remoteInvitationCode = s.getRemoteInvitationCode();
|
||||||
localConfirmationCode = s.getLocalConfirmationCode();
|
localConfirmationCode = s.getLocalConfirmationCode();
|
||||||
remoteConfirmationCode = s.getRemoteConfirmationCode();
|
remoteConfirmationCode = s.getRemoteConfirmationCode();
|
||||||
|
connected = s.getConnected();
|
||||||
connectionFailed = s.getConnectionFailed();
|
connectionFailed = s.getConnectionFailed();
|
||||||
localCompared = s.getLocalCompared();
|
localCompared = s.getLocalCompared();
|
||||||
remoteCompared = s.getRemoteCompared();
|
remoteCompared = s.getRemoteCompared();
|
||||||
@@ -120,10 +121,12 @@ implements InvitationListener {
|
|||||||
setView(new NetworkSetupView(this));
|
setView(new NetworkSetupView(this));
|
||||||
} else if(remoteInvitationCode == -1) {
|
} else if(remoteInvitationCode == -1) {
|
||||||
setView(new InvitationCodeView(this));
|
setView(new InvitationCodeView(this));
|
||||||
} else if(localConfirmationCode == -1) {
|
|
||||||
setView(new ConnectionView(this));
|
|
||||||
} else if(connectionFailed) {
|
} else if(connectionFailed) {
|
||||||
setView(new ConnectionFailedView(this));
|
setView(new ConnectionFailedView(this));
|
||||||
|
} else if(connected && localConfirmationCode == -1) {
|
||||||
|
setView(new ConnectedView(this));
|
||||||
|
} else if(localConfirmationCode == -1) {
|
||||||
|
setView(new ConnectionView(this));
|
||||||
} else if(!localCompared) {
|
} else if(!localCompared) {
|
||||||
setView(new ConfirmationCodeView(this));
|
setView(new ConfirmationCodeView(this));
|
||||||
} else if(!remoteCompared) {
|
} else if(!remoteCompared) {
|
||||||
@@ -296,7 +299,26 @@ implements InvitationListener {
|
|||||||
return contactName;
|
return contactName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionSucceeded(final int localCode, final int remoteCode) {
|
public void connectionSucceeded() {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
connected = true;
|
||||||
|
setView(new ConnectedView(AddContactActivity.this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connectionFailed() {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
connectionFailed = true;
|
||||||
|
setView(new ConnectionFailedView(AddContactActivity.this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyAgreementSucceeded(final int localCode,
|
||||||
|
final int remoteCode) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
localConfirmationCode = localCode;
|
localConfirmationCode = localCode;
|
||||||
@@ -306,7 +328,7 @@ implements InvitationListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionFailed() {
|
public void keyAgreementFailed() {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
connectionFailed = true;
|
connectionFailed = true;
|
||||||
@@ -390,14 +412,22 @@ implements InvitationListener {
|
|||||||
this.handle = handle;
|
this.handle = handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionSucceeded(int localCode, int remoteCode) {
|
public void connectionSucceeded() {
|
||||||
// Wait for remote confirmation to succeed or fail
|
// Wait for key agreement to succeed or fail
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connectionFailed() {
|
public void connectionFailed() {
|
||||||
referenceManager.removeReference(handle, InvitationTask.class);
|
referenceManager.removeReference(handle, InvitationTask.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void keyAgreementSucceeded(int localCode, int remoteCode) {
|
||||||
|
// Wait for remote confirmation to succeed or fail
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyAgreementFailed() {
|
||||||
|
referenceManager.removeReference(handle, InvitationTask.class);
|
||||||
|
}
|
||||||
|
|
||||||
public void remoteConfirmationSucceeded() {
|
public void remoteConfirmationSucceeded() {
|
||||||
// Wait for the pseudonym exchange to succeed or fail
|
// Wait for the pseudonym exchange to succeed or fail
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package net.sf.briar.android.invitation;
|
||||||
|
|
||||||
|
import static android.view.Gravity.CENTER;
|
||||||
|
import net.sf.briar.R;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class ConnectedView extends AddContactView {
|
||||||
|
|
||||||
|
ConnectedView(Context ctx) {
|
||||||
|
super(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void populate() {
|
||||||
|
removeAllViews();
|
||||||
|
Context ctx = getContext();
|
||||||
|
LinearLayout innerLayout = new LinearLayout(ctx);
|
||||||
|
innerLayout.setOrientation(HORIZONTAL);
|
||||||
|
innerLayout.setGravity(CENTER);
|
||||||
|
|
||||||
|
ImageView icon = new ImageView(ctx);
|
||||||
|
icon.setImageResource(R.drawable.navigation_accept);
|
||||||
|
innerLayout.addView(icon);
|
||||||
|
|
||||||
|
TextView connected = new TextView(ctx);
|
||||||
|
connected.setTextSize(22);
|
||||||
|
connected.setPadding(10, 10, 10, 10);
|
||||||
|
connected.setText(R.string.connected_to_contact);
|
||||||
|
innerLayout.addView(connected);
|
||||||
|
addView(innerLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,38 +6,42 @@ package net.sf.briar.api.invitation;
|
|||||||
*/
|
*/
|
||||||
public interface InvitationListener {
|
public interface InvitationListener {
|
||||||
|
|
||||||
/** Called if a connection is established and key agreement succeeds. */
|
/** Called if a connection to the remote peer is established. */
|
||||||
void connectionSucceeded(int localCode, int remoteCode);
|
void connectionSucceeded();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if a connection cannot be established. This indicates that the
|
* Called if a connection to the remote peer cannot be established. This
|
||||||
* protocol has ended unsuccessfully.
|
* indicates that the protocol has ended unsuccessfully.
|
||||||
*/
|
*/
|
||||||
void connectionFailed();
|
void connectionFailed();
|
||||||
|
|
||||||
|
/** Called if key agreement with the remote peer succeeds. */
|
||||||
|
void keyAgreementSucceeded(int localCode, int remoteCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the local peer that the remote peer's confirmation check
|
* Called if key agreement with the remote peer fails or the connection is
|
||||||
* succeeded.
|
* lost. This indicates that the protocol has ended unsuccessfully.
|
||||||
*/
|
*/
|
||||||
|
void keyAgreementFailed();
|
||||||
|
|
||||||
|
/** Called if the remote peer's confirmation check succeeds. */
|
||||||
void remoteConfirmationSucceeded();
|
void remoteConfirmationSucceeded();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the local peer that the remote peer's confirmation check did
|
* Called if remote peer's confirmation check fails or the connection is
|
||||||
* not succeed, or the connection was lost during confirmation. This
|
* lost. This indicates that the protocol has ended unsuccessfully.
|
||||||
* indicates that the protocol has ended unsuccessfully.
|
|
||||||
*/
|
*/
|
||||||
void remoteConfirmationFailed();
|
void remoteConfirmationFailed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the local peer of the name used by the remote peer. Called if
|
* Called if the exchange of pseudonyms succeeds. This indicates that the
|
||||||
* the exchange of pseudonyms succeeds. This indicates that the protocol
|
* protocol has ended successfully.
|
||||||
* has ended successfully.
|
|
||||||
*/
|
*/
|
||||||
void pseudonymExchangeSucceeded(String remoteName);
|
void pseudonymExchangeSucceeded(String remoteName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if the exchange of pseudonyms fails. This indicates that the
|
* Called if the exchange of pseudonyms fails or the connection is lost.
|
||||||
* protocol has ended unsuccessfully.
|
* This indicates that the protocol has ended unsuccessfully.
|
||||||
*/
|
*/
|
||||||
void pseudonymExchangeFailed();
|
void pseudonymExchangeFailed();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,20 +4,21 @@ public class InvitationState {
|
|||||||
|
|
||||||
private final int localInvitationCode, remoteInvitationCode;
|
private final int localInvitationCode, remoteInvitationCode;
|
||||||
private final int localConfirmationCode, remoteConfirmationCode;
|
private final int localConfirmationCode, remoteConfirmationCode;
|
||||||
private final boolean connectionFailed;
|
private final boolean connected, connectionFailed;
|
||||||
private final boolean localCompared, remoteCompared;
|
private final boolean localCompared, remoteCompared;
|
||||||
private final boolean localMatched, remoteMatched;
|
private final boolean localMatched, remoteMatched;
|
||||||
private final String contactName;
|
private final String contactName;
|
||||||
|
|
||||||
public InvitationState(int localInvitationCode, int remoteInvitationCode,
|
public InvitationState(int localInvitationCode, int remoteInvitationCode,
|
||||||
int localConfirmationCode, int remoteConfirmationCode,
|
int localConfirmationCode, int remoteConfirmationCode,
|
||||||
boolean connectionFailed, boolean localCompared,
|
boolean connected, boolean connectionFailed, boolean localCompared,
|
||||||
boolean remoteCompared, boolean localMatched,
|
boolean remoteCompared, boolean localMatched,
|
||||||
boolean remoteMatched, String contactName) {
|
boolean remoteMatched, String contactName) {
|
||||||
this.localInvitationCode = localInvitationCode;
|
this.localInvitationCode = localInvitationCode;
|
||||||
this.remoteInvitationCode = remoteInvitationCode;
|
this.remoteInvitationCode = remoteInvitationCode;
|
||||||
this.localConfirmationCode = localConfirmationCode;
|
this.localConfirmationCode = localConfirmationCode;
|
||||||
this.remoteConfirmationCode = remoteConfirmationCode;
|
this.remoteConfirmationCode = remoteConfirmationCode;
|
||||||
|
this.connected = connected;
|
||||||
this.connectionFailed = connectionFailed;
|
this.connectionFailed = connectionFailed;
|
||||||
this.localCompared = localCompared;
|
this.localCompared = localCompared;
|
||||||
this.remoteCompared = remoteCompared;
|
this.remoteCompared = remoteCompared;
|
||||||
@@ -42,6 +43,10 @@ public class InvitationState {
|
|||||||
return remoteConfirmationCode;
|
return remoteConfirmationCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getConnected() {
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getConnectionFailed() {
|
public boolean getConnectionFailed() {
|
||||||
return connectionFailed;
|
return connectionFailed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,10 +91,12 @@ class AliceConnector extends Connector {
|
|||||||
secret = deriveMasterSecret(hash, key, true);
|
secret = deriveMasterSecret(hash, key, true);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
group.keyAgreementFailed();
|
||||||
tryToClose(conn, true);
|
tryToClose(conn, true);
|
||||||
return;
|
return;
|
||||||
} catch(GeneralSecurityException e) {
|
} catch(GeneralSecurityException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
group.keyAgreementFailed();
|
||||||
tryToClose(conn, true);
|
tryToClose(conn, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -102,7 +104,7 @@ class AliceConnector extends Connector {
|
|||||||
if(LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded");
|
if(LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded");
|
||||||
int[] codes = crypto.deriveConfirmationCodes(secret);
|
int[] codes = crypto.deriveConfirmationCodes(secret);
|
||||||
int aliceCode = codes[0], bobCode = codes[1];
|
int aliceCode = codes[0], bobCode = codes[1];
|
||||||
group.connectionSucceeded(aliceCode, bobCode);
|
group.keyAgreementSucceeded(aliceCode, bobCode);
|
||||||
// Exchange confirmation results
|
// Exchange confirmation results
|
||||||
try {
|
try {
|
||||||
sendConfirmation(w);
|
sendConfirmation(w);
|
||||||
|
|||||||
@@ -91,10 +91,12 @@ class BobConnector extends Connector {
|
|||||||
secret = deriveMasterSecret(hash, key, false);
|
secret = deriveMasterSecret(hash, key, false);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
group.keyAgreementFailed();
|
||||||
tryToClose(conn, true);
|
tryToClose(conn, true);
|
||||||
return;
|
return;
|
||||||
} catch(GeneralSecurityException e) {
|
} catch(GeneralSecurityException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
group.keyAgreementFailed();
|
||||||
tryToClose(conn, true);
|
tryToClose(conn, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -102,7 +104,7 @@ class BobConnector extends Connector {
|
|||||||
if(LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded");
|
if(LOG.isLoggable(INFO)) LOG.info(pluginName + " agreement succeeded");
|
||||||
int[] codes = crypto.deriveConfirmationCodes(secret);
|
int[] codes = crypto.deriveConfirmationCodes(secret);
|
||||||
int aliceCode = codes[0], bobCode = codes[1];
|
int aliceCode = codes[0], bobCode = codes[1];
|
||||||
group.connectionSucceeded(bobCode, aliceCode);
|
group.keyAgreementSucceeded(bobCode, aliceCode);
|
||||||
// Exchange confirmation results
|
// Exchange confirmation results
|
||||||
try {
|
try {
|
||||||
if(receiveConfirmation(r)) group.remoteConfirmationSucceeded();
|
if(receiveConfirmation(r)) group.remoteConfirmationSucceeded();
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
|||||||
public synchronized InvitationState addListener(InvitationListener l) {
|
public synchronized InvitationState addListener(InvitationListener l) {
|
||||||
listeners.add(l);
|
listeners.add(l);
|
||||||
return new InvitationState(localInvitationCode, remoteInvitationCode,
|
return new InvitationState(localInvitationCode, remoteInvitationCode,
|
||||||
localConfirmationCode, remoteConfirmationCode,
|
localConfirmationCode, remoteConfirmationCode, connected.get(),
|
||||||
connectionFailed, localCompared, remoteCompared, localMatched,
|
connectionFailed, localCompared, remoteCompared, localMatched,
|
||||||
remoteMatched, remoteName);
|
remoteMatched, remoteName);
|
||||||
}
|
}
|
||||||
@@ -202,16 +202,24 @@ class ConnectorGroup extends Thread implements InvitationTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean getAndSetConnected() {
|
boolean getAndSetConnected() {
|
||||||
return connected.getAndSet(true);
|
boolean redundant = connected.getAndSet(true);
|
||||||
|
if(!redundant) {
|
||||||
|
for(InvitationListener l : listeners) l.connectionSucceeded();
|
||||||
|
}
|
||||||
|
return redundant;
|
||||||
}
|
}
|
||||||
|
|
||||||
void connectionSucceeded(int localCode, int remoteCode) {
|
void keyAgreementSucceeded(int localCode, int remoteCode) {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
localConfirmationCode = localCode;
|
localConfirmationCode = localCode;
|
||||||
remoteConfirmationCode = remoteCode;
|
remoteConfirmationCode = remoteCode;
|
||||||
}
|
}
|
||||||
for(InvitationListener l : listeners)
|
for(InvitationListener l : listeners)
|
||||||
l.connectionSucceeded(localCode, remoteCode);
|
l.keyAgreementSucceeded(localCode, remoteCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyAgreementFailed() {
|
||||||
|
for(InvitationListener l : listeners) l.keyAgreementFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void remoteConfirmationSucceeded() {
|
void remoteConfirmationSucceeded() {
|
||||||
|
|||||||
Reference in New Issue
Block a user