diff --git a/app/src/main/cpp/monerujo.cpp b/app/src/main/cpp/monerujo.cpp index 308e10d..088867e 100644 --- a/app/src/main/cpp/monerujo.cpp +++ b/app/src/main/cpp/monerujo.cpp @@ -592,12 +592,16 @@ Java_com_m2049r_xmrwallet_model_Wallet_getFilename(JNIEnv *env, jobject instance JNIEXPORT jboolean JNICALL Java_com_m2049r_xmrwallet_model_Wallet_initJ(JNIEnv *env, jobject instance, jstring daemon_address, - jlong upper_transaction_size_limit) { -// const std::string &daemon_username = "", const std::string &daemon_password = "") = 0; + jlong upper_transaction_size_limit, + jstring daemon_username, jstring daemon_password) { const char *_daemon_address = env->GetStringUTFChars(daemon_address, JNI_FALSE); + const char *_daemon_username = env->GetStringUTFChars(daemon_username, JNI_FALSE); + const char *_daemon_password = env->GetStringUTFChars(daemon_password, JNI_FALSE); Bitmonero::Wallet *wallet = getHandle(env, instance); - bool status = wallet->init(_daemon_address, upper_transaction_size_limit); + bool status = wallet->init(_daemon_address, upper_transaction_size_limit, _daemon_username, _daemon_password); env->ReleaseStringUTFChars(daemon_address, _daemon_address); + env->ReleaseStringUTFChars(daemon_username, _daemon_username); + env->ReleaseStringUTFChars(daemon_password, _daemon_password); return status; } diff --git a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java index 7705c9d..c9df5ae 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java +++ b/app/src/main/java/com/m2049r/xmrwallet/LoginFragment.java @@ -322,48 +322,58 @@ public class LoginFragment extends Fragment { editor.apply(); } - private boolean checkAndSetWalletDaemon(String daemonAddress, boolean testnet) { - if (!daemonAddress.isEmpty()) { - String d[] = daemonAddress.split(":"); - if (d.length > 2) return false; - if (d.length < 1) return false; - String host = d[0]; + private boolean checkAndSetWalletDaemon(String daemon, boolean testnet) { + String daemonAddress = ""; + String username = ""; + String password = ""; + if (!daemon.isEmpty()) { // no actual daemon is also fine + String a[] = daemon.split("@"); + if (a.length == 1) { // no credentials + daemonAddress = a[0]; + } else if (a.length == 2) { // credentials + String up[] = a[0].split(":"); + if (up.length != 2) return false; + username = up[0]; + if (!username.isEmpty()) password = up[1]; + daemonAddress = a[1]; + } else { + return false; + } + + String da[] = daemonAddress.split(":"); + if ((da.length > 2) || (da.length < 1)) return false; + String host = da[0]; int port; - if (d.length == 2) { + if (da.length == 2) { try { - port = Integer.parseInt(d[1]); + port = Integer.parseInt(da[1]); } catch (NumberFormatException ex) { return false; } } else { port = (testnet ? 28081 : 18081); } + //Log.d(TAG, "DAEMON " + username + "/" + password + "/" + host + "/" + port); // if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy prevPolicy = StrictMode.getThreadPolicy(); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder(prevPolicy).permitNetwork().build(); StrictMode.setThreadPolicy(policy); Socket socket = new Socket(); - long a = new Date().getTime(); + long timeA = new Date().getTime(); try { socket.connect(new InetSocketAddress(host, port), LoginActivity.DAEMON_TIMEOUT); socket.close(); } catch (IOException ex) { - Log.d(TAG, "Cannot reach daemon " + host + ":" + port + " because " + ex.getLocalizedMessage()); + Log.d(TAG, "Cannot reach daemon " + host + "/" + port + " because " + ex.getLocalizedMessage()); return false; } finally { StrictMode.setThreadPolicy(prevPolicy); } - long b = new Date().getTime(); - Log.d(TAG, "Daemon is " + (b - a) + "ms away."); + long timeB = new Date().getTime(); + Log.d(TAG, "Daemon is " + (timeB - timeA) + "ms away."); } WalletManager mgr = WalletManager.getInstance(); - mgr.setDaemon(daemonAddress, testnet); - if (!daemonAddress.isEmpty()) { - int version = mgr.getDaemonVersion(); - Log.d(TAG, "Daemon is v" + version); - return (version >= WalletActivity.MIN_DAEMON_VERSION); - } else { - return true; - } + mgr.setDaemon(daemonAddress, testnet, username, password); + return true; } } diff --git a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java index 9e57d69..b06e56f 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java +++ b/app/src/main/java/com/m2049r/xmrwallet/WalletActivity.java @@ -42,8 +42,6 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment. WalletService.Observer, SendFragment.Listener, TxFragment.Listener, GenerateReviewFragment.ListenerWithWallet { private static final String TAG = "WalletActivity"; - static final int MIN_DAEMON_VERSION = 65544; - public static final String REQUEST_ID = "id"; public static final String REQUEST_PW = "pw"; @@ -342,6 +340,20 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment. }); } + @Override + public void onWalletStarted(final boolean success) { + runOnUiThread(new Runnable() { + public void run() { + if (!success) { + Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_failed), Toast.LENGTH_LONG).show(); + } + } + }); + if (!success) { + finish(); + } + } + @Override public void onCreatedTransaction(final PendingTransaction pendingTransaction) { try { diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java index c36a2e1..fde4417 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/Wallet.java @@ -96,10 +96,13 @@ public class Wallet { // virtual std::string keysFilename() const = 0; public boolean init(long upper_transaction_size_limit) { - return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit); + return initJ(WalletManager.getInstance().getDaemonAddress(), upper_transaction_size_limit, + WalletManager.getInstance().getDaemonUsername(), + WalletManager.getInstance().getDaemonPassword()); } - private native boolean initJ(String daemon_address, long upper_transaction_size_limit); + private native boolean initJ(String daemon_address, long upper_transaction_size_limit, + String daemon_username, String daemon_password); // virtual bool createWatchOnly(const std::string &path, const std::string &password, const std::string &language) const = 0; // virtual void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) = 0; diff --git a/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java b/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java index dc03a94..3cf5fb5 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java +++ b/app/src/main/java/com/m2049r/xmrwallet/model/WalletManager.java @@ -197,9 +197,12 @@ public class WalletManager { return testnet; } - public void setDaemon(String address, boolean testnet) { + public void setDaemon(String address, boolean testnet, String username, String password) { + //Log.d(TAG, "SETDAEMON " + username + "/" + password + "/" + address); this.daemonAddress = address; this.testnet = testnet; + this.daemonUsername = username; + this.daemonPassword = password; setDaemonAddressJ(address); } @@ -213,6 +216,18 @@ public class WalletManager { private native void setDaemonAddressJ(String address); + String daemonUsername = ""; + + public String getDaemonUsername() { + return daemonUsername; + } + + String daemonPassword = ""; + + public String getDaemonPassword() { + return daemonPassword; + } + public native int getDaemonVersion(); public native long getBlockchainHeight(); diff --git a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java index 0142f8a..c574d2f 100644 --- a/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java +++ b/app/src/main/java/com/m2049r/xmrwallet/service/WalletService.java @@ -224,6 +224,8 @@ public class WalletService extends Service { void onSentTransaction(boolean success); void onSetNotes(boolean success); + + void onWalletStarted(boolean success); } String progressText = null; @@ -263,6 +265,8 @@ public class WalletService extends Service { private Looper mServiceLooper; private WalletService.ServiceHandler mServiceHandler; + private boolean errorState = false; + // Handler that receives messages from the thread private final class ServiceHandler extends Handler { ServiceHandler(Looper looper) { @@ -272,6 +276,11 @@ public class WalletService extends Service { @Override public void handleMessage(Message msg) { Log.d(TAG, "Handling " + msg.arg2); + if (errorState) { + Log.i(TAG, "In error state."); + // also, we have already stopped ourselves + return; + } switch (msg.arg2) { case START_SERVICE: { Bundle extras = msg.getData(); @@ -283,7 +292,12 @@ public class WalletService extends Service { if (walletId != null) { showProgress(getString(R.string.status_wallet_loading)); showProgress(10); - start(walletId, walletPw); // TODO What if this fails? + boolean success = start(walletId, walletPw); + if (observer != null) observer.onWalletStarted(success); + if (!success) { + errorState = true; + stop(); + } } } else if (cmd.equals(REQUEST_CMD_STORE)) { Wallet myWallet = getWallet(); @@ -461,7 +475,7 @@ public class WalletService extends Service { return true; // true is important so that onUnbind is also called next time } - private void start(String walletName, String walletPassword) { + private boolean start(String walletName, String walletPassword) { startNotfication(); // if there is an listener it is always started / syncing Log.d(TAG, "start()"); @@ -470,7 +484,10 @@ public class WalletService extends Service { if (listener == null) { Log.d(TAG, "start() loadWallet"); Wallet aWallet = loadWallet(walletName, walletPassword); - // TODO check aWallet and die gracefully if neccessary + if ((aWallet == null) || (aWallet.getConnectionStatus() != Wallet.ConnectionStatus.ConnectionStatus_Connected)) { + if (aWallet != null) aWallet.close(); + return false; + } listener = new MyWalletListener(aWallet); listener.start(); showProgress(100); @@ -480,6 +497,7 @@ public class WalletService extends Service { // if we try to refresh the history here we get occasional segfaults! // doesnt matter since we update as soon as we get a new block anyway Log.d(TAG, "start() done"); + return true; } public void stop() { @@ -512,7 +530,7 @@ public class WalletService extends Service { showProgress(55); wallet.init(0); showProgress(90); - Log.d(TAG, wallet.getConnectionStatus().toString()); + //Log.d(TAG, wallet.getConnectionStatus().toString()); } return wallet; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a1a1936..bb505e1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,6 +13,7 @@ Wallet saved Wallet save failed! Connecting … + Daemon connection failed!\nCheck username/password Working on it … Transaction sent!