From 07bf1e9ebccb25681f25e04424e8f03fa5807486 Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Sat, 5 Oct 2013 17:25:59 +0200 Subject: [PATCH] Made sendPackage sync, so mutex hack in Device is no longer needed --- .../org/kde/kdeconnect/Backends/BaseLink.java | 2 +- .../Backends/LanBackend/LanLink.java | 76 +++++++++++-------- .../main/java/org/kde/kdeconnect/Device.java | 28 +++---- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/BaseLink.java b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/BaseLink.java index 59d13e8b..4800f05b 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/BaseLink.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/BaseLink.java @@ -56,7 +56,7 @@ public abstract class BaseLink { } } - //TO OVERRIDE + //TO OVERRIDE, should be sync public abstract boolean sendPackage(NetworkPackage np); public abstract boolean sendPackageEncrypted(NetworkPackage np, PublicKey key); diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLink.java b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLink.java index 3cc7106c..e30a2f21 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLink.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLink.java @@ -1,36 +1,20 @@ package org.kde.kdeconnect.Backends.LanBackend; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.Base64; import android.util.Log; -import org.apache.mina.core.future.ConnectFuture; -import org.apache.mina.core.future.IoFuture; -import org.apache.mina.core.future.IoFutureListener; -import org.apache.mina.core.service.IoHandlerAdapter; +import org.apache.mina.core.future.WriteFuture; import org.apache.mina.core.session.IoSession; -import org.apache.mina.filter.codec.ProtocolCodecFilter; -import org.apache.mina.filter.codec.textline.LineDelimiter; -import org.apache.mina.filter.codec.textline.TextLineCodecFactory; -import org.apache.mina.transport.socket.nio.NioSocketConnector; import org.json.JSONObject; import org.kde.kdeconnect.Backends.BaseLink; import org.kde.kdeconnect.Backends.BaseLinkProvider; import org.kde.kdeconnect.NetworkPackage; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; -import java.net.SocketAddress; -import java.nio.charset.Charset; -import java.security.KeyFactory; -import java.security.PrivateKey; import java.security.PublicKey; -import java.security.spec.PKCS8EncodedKeySpec; public class LanLink extends BaseLink { @@ -46,10 +30,12 @@ public class LanLink extends BaseLink { this.session = session; } - private JSONObject sendPayload(final InputStream stream) { + private Thread sendPayload(NetworkPackage np) { try { + final InputStream stream = np.getPayload(); + ServerSocket candidateServer = null; boolean success = false; int tcpPort = 1739; @@ -61,14 +47,17 @@ public class LanLink extends BaseLink { } catch(Exception e) { Log.e("LanLink", "Exception openning serversocket: "+e); tcpPort++; - if (tcpPort >= 1764) return new JSONObject(); + if (tcpPort >= 1764) { + Log.e("LanLink", "No more ports available"); + return null; + } } } JSONObject payloadTransferInfo = new JSONObject(); payloadTransferInfo.put("port", tcpPort); final ServerSocket server = candidateServer; - new Thread(new Runnable() { + Thread thread = new Thread(new Runnable() { @Override public void run() { //TODO: Timeout when waiting for a connection and close the socket @@ -93,9 +82,12 @@ public class LanLink extends BaseLink { try { server.close(); } catch(Exception e) { } } } - }).start(); + }); + thread.start(); - return payloadTransferInfo; + np.setPayloadTransferInfo(payloadTransferInfo); + + return thread; } catch(Exception e) { @@ -108,19 +100,33 @@ public class LanLink extends BaseLink { } @Override public boolean sendPackage(final NetworkPackage np) { + if (session == null) { Log.e("LanLink", "sendPackage failed: not yet connected"); return false; } - if (np.hasPayload()) { - JSONObject transferInfo = sendPayload(np.getPayload()); - np.setPayloadTransferInfo(transferInfo); + try { + Thread thread = null; + if (np.hasPayload()) { + thread = sendPayload(np); + if (thread == null) return false; + } + + WriteFuture future = session.write(np.serialize()); + if (!future.await().isWritten()) return false; + + if (thread != null) { + thread.join(); //Wait for thread to finish + } + + return true; + } catch (Exception e) { + e.printStackTrace(); + Log.e("LanLink", "sendPackage exception"); + return false; } - session.write(np.serialize()); - - return true; } @Override @@ -133,19 +139,25 @@ public class LanLink extends BaseLink { try { + Thread thread = null; if (np.hasPayload()) { - JSONObject transferInfo = sendPayload(np.getPayload()); - np.setPayloadTransferInfo(transferInfo); + thread = sendPayload(np); + if (thread == null) return false; } np.encrypt(key); + WriteFuture future = session.write(np.serialize()); + if (!future.await().isWritten()) return false; - session.write(np.serialize()); + if (thread != null) { + thread.join(); //Wait for thread to finish + } return true; + } catch (Exception e) { e.printStackTrace(); - Log.e("LanLink", "Encryption exception"); + Log.e("LanLink", "sendPackageEncrypted exception"); return false; } diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java b/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java index e89ea389..b06ea7a0 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java @@ -7,7 +7,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; -import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; @@ -33,8 +32,6 @@ import java.util.HashMap; import java.util.Set; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; public class Device implements BaseLink.PackageReceiver { @@ -443,23 +440,22 @@ public class Device implements BaseLink.PackageReceiver { sendPackage(np,null); } - private Lock mutex = new ReentrantLock(true); - + //Async public void sendPackage(final NetworkPackage np, final SendPackageFinishedCallback callback) { - new Thread(new Runnable() { @Override public void run() { - mutex.lock(); - - //Log.e("sendPackage", "Sending..."); + //Log.e("sendPackage", "Sending package..."); boolean useEncryption = (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()); + //We need a copy to avoid concurrent modification exception if the original list changes + ArrayList mLinks = new ArrayList(links); + boolean success = false; - for(BaseLink link : links) { + for(BaseLink link : mLinks) { if (useEncryption) { success = link.sendPackageEncrypted(np, publicKey); } else { @@ -468,18 +464,16 @@ public class Device implements BaseLink.PackageReceiver { if (success) break; } - if (callback != null) { - if (success) callback.sendSuccessful(); - else callback.sendFailed(); - } - if (success) { - //Log.e("sendPackage","sent"); + // Log.e("sendPackage","Package sent"); } else { Log.e("sendPackage","Error: Package could not be sent ("+links.size()+" links available)"); } - mutex.unlock(); + if (callback != null) { + if (success) callback.sendSuccessful(); + else callback.sendFailed(); + } } }).start();