tls-psk: working version, with fake progress too!
This commit is contained in:
@@ -22,6 +22,7 @@ import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.Socket;
|
||||
@@ -53,9 +54,11 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
@RequiresApi(api = VERSION_CODES.LOLLIPOP)
|
||||
public class KeyTransferInteractor {
|
||||
private static final int SHOW_CONNECTION_DETAILS = 1;
|
||||
private static final int CONNECTION_LISTENING = 1;
|
||||
private static final int CONNECTION_ESTABLISHED = 2;
|
||||
private static final int CONNECTION_LOST = 3;
|
||||
private static final int CONNECTION_SEND_OK = 3;
|
||||
private static final int CONNECTION_RECEIVE_OK = 4;
|
||||
private static final int CONNECTION_LOST = 5;
|
||||
|
||||
|
||||
private TransferThread transferThread;
|
||||
@@ -121,7 +124,7 @@ public class KeyTransferInteractor {
|
||||
|
||||
String presharedKeyEncoded = Base64.encodeToString(presharedKey, Base64.URL_SAFE | Base64.NO_PADDING);
|
||||
String qrCodeData = presharedKeyEncoded + "@" + getIPAddress(true) + ":" + port;
|
||||
invokeListener(SHOW_CONNECTION_DETAILS, qrCodeData);
|
||||
invokeListener(CONNECTION_LISTENING, qrCodeData);
|
||||
|
||||
socket = serverSocket.accept();
|
||||
invokeListener(CONNECTION_ESTABLISHED, socket.getInetAddress().toString());
|
||||
@@ -131,6 +134,7 @@ public class KeyTransferInteractor {
|
||||
}
|
||||
|
||||
handleOpenConnection(socket);
|
||||
Log.d(Constants.TAG, "connection closed ok!");
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "error!", e);
|
||||
} finally {
|
||||
@@ -164,33 +168,70 @@ public class KeyTransferInteractor {
|
||||
}
|
||||
|
||||
private void handleOpenConnection(Socket socket) throws IOException {
|
||||
socket.setSoTimeout(500);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
|
||||
socket.setSoTimeout(500);
|
||||
while (!isInterrupted() && socket.isConnected()) {
|
||||
if (dataToSend != null) {
|
||||
BufferedOutputStream bufferedOutputStream =
|
||||
new BufferedOutputStream(socket.getOutputStream());
|
||||
bufferedOutputStream.write(dataToSend);
|
||||
bufferedOutputStream.close();
|
||||
dataToSend = null;
|
||||
break;
|
||||
if (sendDataIfAvailable(socket)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String line = bufferedReader.readLine();
|
||||
if (line == null) {
|
||||
Log.d(Constants.TAG, "eof");
|
||||
break;
|
||||
}
|
||||
Log.d(Constants.TAG, "got line: " + line);
|
||||
} catch (SocketTimeoutException e) {
|
||||
// ignore
|
||||
|
||||
if (receiveDataIfAvailable(socket, bufferedReader)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.d(Constants.TAG, "disconnected");
|
||||
invokeListener(CONNECTION_LOST, null);
|
||||
}
|
||||
|
||||
private boolean receiveDataIfAvailable(Socket socket, BufferedReader bufferedReader) throws IOException {
|
||||
String firstLine;
|
||||
try {
|
||||
firstLine = bufferedReader.readLine();
|
||||
} catch (SocketTimeoutException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (firstLine == null) {
|
||||
invokeListener(CONNECTION_LOST, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
socket.setSoTimeout(2000);
|
||||
String receivedData = receiveAfterFirstLineAndClose(bufferedReader, firstLine);
|
||||
invokeListener(CONNECTION_RECEIVE_OK, receivedData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean sendDataIfAvailable(Socket socket) throws IOException {
|
||||
if (dataToSend != null) {
|
||||
byte[] data = dataToSend;
|
||||
dataToSend = null;
|
||||
|
||||
socket.setSoTimeout(2000);
|
||||
sendDataAndClose(socket.getOutputStream(), data);
|
||||
invokeListener(CONNECTION_SEND_OK, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String receiveAfterFirstLineAndClose(BufferedReader bufferedReader, String line) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
do {
|
||||
builder.append(line);
|
||||
line = bufferedReader.readLine();
|
||||
} while (line != null);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void sendDataAndClose(OutputStream outputStream, byte[] data) throws IOException {
|
||||
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
|
||||
bufferedOutputStream.write(data);
|
||||
bufferedOutputStream.close();
|
||||
}
|
||||
|
||||
private void invokeListener(final int method, final String arg) {
|
||||
if (handler == null) {
|
||||
return;
|
||||
@@ -203,12 +244,18 @@ public class KeyTransferInteractor {
|
||||
return;
|
||||
}
|
||||
switch (method) {
|
||||
case SHOW_CONNECTION_DETAILS:
|
||||
case CONNECTION_LISTENING:
|
||||
callback.onServerStarted(arg);
|
||||
break;
|
||||
case CONNECTION_ESTABLISHED:
|
||||
callback.onConnectionEstablished(arg);
|
||||
break;
|
||||
case CONNECTION_RECEIVE_OK:
|
||||
callback.onDataReceivedOk(arg);
|
||||
break;
|
||||
case CONNECTION_SEND_OK:
|
||||
callback.onDataSentOk(arg);
|
||||
break;
|
||||
case CONNECTION_LOST:
|
||||
callback.onConnectionLost();
|
||||
}
|
||||
@@ -218,7 +265,7 @@ public class KeyTransferInteractor {
|
||||
handler.post(runnable);
|
||||
}
|
||||
|
||||
public synchronized void sendDataAndClose(byte[] dataToSend) {
|
||||
synchronized void sendDataAndClose(byte[] dataToSend) {
|
||||
this.dataToSend = dataToSend;
|
||||
}
|
||||
|
||||
@@ -258,6 +305,9 @@ public class KeyTransferInteractor {
|
||||
void onServerStarted(String qrCodeData);
|
||||
void onConnectionEstablished(String otherName);
|
||||
void onConnectionLost();
|
||||
|
||||
void onDataReceivedOk(String receivedData);
|
||||
void onDataSentOk(String arg);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,7 +343,8 @@ public class KeyTransferInteractor {
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} // for now eat exceptions
|
||||
// ignore
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.network.KeyTransferInteractor;
|
||||
import org.sufficientlysecure.keychain.network.KeyTransferInteractor.KeyTransferCallback;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
@@ -42,6 +43,7 @@ import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader.Secret
|
||||
import org.sufficientlysecure.keychain.ui.transfer.view.TransferSecretKeyList.OnClickTransferKeyListener;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.view.TransferSecretKeyList.TransferKeyAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
|
||||
@RequiresApi(api = VERSION_CODES.LOLLIPOP)
|
||||
@@ -66,43 +68,45 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
view.setSecretKeyAdapter(secretKeyAdapter);
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
|
||||
public void onUiStart() {
|
||||
loaderManager.restartLoader(loaderId, null, this);
|
||||
|
||||
startServer();
|
||||
if (keyTransferServerInteractor == null && keyTransferClientInteractor == null) {
|
||||
connectionStartListen();
|
||||
}
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
clearConnections();
|
||||
public void onUiStop() {
|
||||
connectionClear();
|
||||
}
|
||||
|
||||
public void onClickScan() {
|
||||
clearConnections();
|
||||
public void onUiClickScan() {
|
||||
connectionClear();
|
||||
|
||||
view.scanQrCode();
|
||||
}
|
||||
|
||||
public void onQrCodeScanned(String qrCodeContent) {
|
||||
keyTransferClientInteractor = new KeyTransferInteractor();
|
||||
keyTransferClientInteractor.connectToServer(qrCodeContent, this);
|
||||
public void onUiQrCodeScanned(String qrCodeContent) {
|
||||
connectionStartConnect(qrCodeContent);
|
||||
}
|
||||
|
||||
private void clearConnections() {
|
||||
if (keyTransferServerInteractor != null) {
|
||||
keyTransferServerInteractor.closeConnection();
|
||||
keyTransferServerInteractor = null;
|
||||
}
|
||||
if (keyTransferClientInteractor != null) {
|
||||
keyTransferClientInteractor.closeConnection();
|
||||
keyTransferClientInteractor = null;
|
||||
@Override
|
||||
public void onUiClickTransferKey(long masterKeyId) {
|
||||
try {
|
||||
byte[] armoredSecretKey =
|
||||
KeyRepository.createDatabaseInteractor(context).getSecretKeyRingAsArmoredData(masterKeyId);
|
||||
connectionSend(armoredSecretKey);
|
||||
} catch (IOException | NotFoundException | PgpGeneralException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void startServer() {
|
||||
keyTransferServerInteractor = new KeyTransferInteractor();
|
||||
keyTransferServerInteractor.startServer(this);
|
||||
public void onUiFakeProgressFinished() {
|
||||
view.showKeySentOk();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onServerStarted(String qrCodeData) {
|
||||
Bitmap qrCodeBitmap = QrCodeUtils.getQRCodeBitmap(Uri.parse("pgp+transfer://" + qrCodeData));
|
||||
@@ -116,10 +120,57 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
|
||||
@Override
|
||||
public void onConnectionLost() {
|
||||
view.showWaitingForConnection();
|
||||
startServer();
|
||||
connectionStartListen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataReceivedOk(String receivedData) {
|
||||
Log.d(Constants.TAG, "received: " + receivedData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataSentOk(String arg) {
|
||||
Log.d(Constants.TAG, "data sent ok!");
|
||||
view.showFakeSendProgressDialog();
|
||||
}
|
||||
|
||||
|
||||
private void connectionStartConnect(String qrCodeContent) {
|
||||
connectionClear();
|
||||
|
||||
keyTransferClientInteractor = new KeyTransferInteractor();
|
||||
keyTransferClientInteractor.connectToServer(qrCodeContent, this);
|
||||
}
|
||||
|
||||
private void connectionStartListen() {
|
||||
connectionClear();
|
||||
|
||||
keyTransferServerInteractor = new KeyTransferInteractor();
|
||||
keyTransferServerInteractor.startServer(this);
|
||||
|
||||
view.showWaitingForConnection();
|
||||
}
|
||||
|
||||
private void connectionClear() {
|
||||
if (keyTransferServerInteractor != null) {
|
||||
keyTransferServerInteractor.closeConnection();
|
||||
keyTransferServerInteractor = null;
|
||||
}
|
||||
if (keyTransferClientInteractor != null) {
|
||||
keyTransferClientInteractor.closeConnection();
|
||||
keyTransferClientInteractor = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void connectionSend(byte[] armoredSecretKey) {
|
||||
if (keyTransferClientInteractor != null) {
|
||||
keyTransferClientInteractor.sendData(armoredSecretKey);
|
||||
} else if (keyTransferServerInteractor != null) {
|
||||
keyTransferServerInteractor.sendData(armoredSecretKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Loader<List<SecretKeyItem>> onCreateLoader(int id, Bundle args) {
|
||||
return secretKeyAdapter.createLoader(context);
|
||||
@@ -135,20 +186,6 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
secretKeyAdapter.setData(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClickTransferKey(long masterKeyId) {
|
||||
try {
|
||||
byte[] armoredSecretKey =
|
||||
KeyRepository.createDatabaseInteractor(context).getSecretKeyRingAsArmoredData(masterKeyId);
|
||||
if (keyTransferClientInteractor != null) {
|
||||
keyTransferClientInteractor.sendData(armoredSecretKey);
|
||||
} else if (keyTransferServerInteractor != null) {
|
||||
keyTransferServerInteractor.sendData(armoredSecretKey);
|
||||
}
|
||||
} catch (IOException | NotFoundException | PgpGeneralException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public interface TransferMvpView {
|
||||
void showWaitingForConnection();
|
||||
@@ -158,5 +195,8 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
void setQrImage(Bitmap qrCode);
|
||||
|
||||
void setSecretKeyAdapter(Adapter adapter);
|
||||
|
||||
void showFakeSendProgressDialog();
|
||||
void showKeySentOk();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,16 @@
|
||||
package org.sufficientlysecure.keychain.ui.transfer.view;
|
||||
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -40,6 +45,7 @@ import android.widget.ViewAnimator;
|
||||
import com.google.zxing.client.android.Intents;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.QrCodeCaptureActivity;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.TransferMvpView;
|
||||
|
||||
@@ -48,6 +54,8 @@ import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.T
|
||||
public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
public static final int VIEW_WAITING = 0;
|
||||
public static final int VIEW_CONNECTED = 1;
|
||||
public static final int VIEW_SEND_OK = 2;
|
||||
|
||||
public static final int REQUEST_CODE_SCAN = 1;
|
||||
public static final int LOADER_ID = 1;
|
||||
|
||||
@@ -74,7 +82,7 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (presenter != null) {
|
||||
presenter.onClickScan();
|
||||
presenter.onUiClickScan();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -94,14 +102,14 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
presenter.onStart();
|
||||
presenter.onUiStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
presenter.onStop();
|
||||
presenter.onUiStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,8 +119,13 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
|
||||
@Override
|
||||
public void showConnectionEstablished(String hostname) {
|
||||
vTransferAnimator.setDisplayedChild(VIEW_CONNECTED);
|
||||
vConnectionStatusText.setText("Connected to: " + hostname);
|
||||
vTransferAnimator.setDisplayedChild(VIEW_CONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showKeySentOk() {
|
||||
vTransferAnimator.setDisplayedChild(VIEW_SEND_OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,13 +154,44 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
vTransferKeyList.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showFakeSendProgressDialog() {
|
||||
final ProgressDialogFragment progressDialogFragment =
|
||||
ProgressDialogFragment.newInstance("Sending key…", ProgressDialog.STYLE_HORIZONTAL, false);
|
||||
progressDialogFragment.show(getFragmentManager(), "progress");
|
||||
|
||||
final Handler handler = new Handler();
|
||||
|
||||
Timer timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
int fakeProgress = 0;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
fakeProgress += 6;
|
||||
if (fakeProgress > 100) {
|
||||
cancel();
|
||||
progressDialogFragment.dismissAllowingStateLoss();
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
presenter.onUiFakeProgressFinished();
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
progressDialogFragment.setProgress(fakeProgress, 100);
|
||||
}
|
||||
}, 0, 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_SCAN:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
String qrCodeData = data.getStringExtra(Intents.Scan.RESULT);
|
||||
presenter.onQrCodeScanned(qrCodeData);
|
||||
presenter.onUiQrCodeScanned(qrCodeData);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -129,7 +129,7 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
vSendButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onClickTransferKeyListener.onClickTransferKey(item.masterKeyId);
|
||||
onClickTransferKeyListener.onUiClickTransferKey(item.masterKeyId);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -139,6 +139,6 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
}
|
||||
|
||||
public interface OnClickTransferKeyListener {
|
||||
void onClickTransferKey(long masterKeyId);
|
||||
void onUiClickTransferKey(long masterKeyId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user