From 754123b9c552c9c8c86d448bcd9471c91747bcdd Mon Sep 17 00:00:00 2001 From: Albert Vaca Date: Fri, 27 Sep 2013 00:07:14 +0200 Subject: [PATCH] Fixed bugs with file transfers Finding open ports was not working (socked became closed after first try) AsyncTask on Device's sendPackage was blocking execution when stuck sending --- KdeConnect/KdeConnect.iml | 8 +- .../Backends/LanBackend/LanLink.java | 32 +++++--- .../Backends/LanBackend/LanLinkProvider.java | 77 +++++++++---------- .../main/java/org/kde/kdeconnect/Device.java | 22 +++--- .../org/kde/kdeconnect/NetworkPackage.java | 2 +- kdeconnect-android.iml | 2 +- 6 files changed, 76 insertions(+), 67 deletions(-) diff --git a/KdeConnect/KdeConnect.iml b/KdeConnect/KdeConnect.iml index 79344f5d..22a89c1c 100644 --- a/KdeConnect/KdeConnect.iml +++ b/KdeConnect/KdeConnect.iml @@ -1,10 +1,11 @@ - + 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 ccd44477..647d766e 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 @@ -37,7 +37,7 @@ public class LanLink extends BaseLink { private IoSession session = null; public void disconnect() { - Log.i("LanLink","Disconnect: "+session.getRemoteAddress().toString()); + Log.i("LanLink", "Disconnect: "+session.getRemoteAddress().toString()); session.close(true); } @@ -50,40 +50,47 @@ public class LanLink extends BaseLink { try { - final ServerSocket server = new ServerSocket(); + ServerSocket candidateServer = null; boolean success = false; - int tcpPort = 1764; + int tcpPort = 1739; while(!success) { try { - server.bind(new InetSocketAddress(tcpPort)); + candidateServer = new ServerSocket(); + candidateServer.bind(new InetSocketAddress(tcpPort)); success = true; } catch(Exception e) { + Log.e("LanLink", "Exception openning serversocket: "+e); tcpPort++; + if (tcpPort >= 1764) return new JSONObject(); } } - JSONObject payloadTransferInfo = new JSONObject(); payloadTransferInfo.put("port", tcpPort); + final ServerSocket server = candidateServer; new Thread(new Runnable() { @Override public void run() { //TODO: Timeout when waiting for a connection and close the socket + OutputStream socket = null; try { - OutputStream socket = server.accept().getOutputStream(); - byte[] buffer = new byte[2048]; + socket = server.accept().getOutputStream(); + byte[] buffer = new byte[4096]; int bytesRead; Log.e("LanLink","Beginning to send payload"); while ((bytesRead = stream.read(buffer)) != -1) { - Log.e("ok",""+bytesRead); + //Log.e("ok",""+bytesRead); socket.write(buffer, 0, bytesRead); } - socket.close(); - server.close(); Log.e("LanLink","Finished sending payload"); } catch(Exception e) { e.printStackTrace(); Log.e("LanLink", "Exception with payload upload socket"); + } finally { + if (socket != null) { + try { socket.close(); } catch(Exception e) { } + } + try { server.close(); } catch(Exception e) { } } } }).start(); @@ -118,18 +125,23 @@ public class LanLink extends BaseLink { @Override public boolean sendPackageEncrypted(NetworkPackage np, PublicKey key) { + if (session == null) { Log.e("LanLink","sendPackage failed: not yet connected"); return false; } try { + if (np.hasPayload()) { JSONObject transferInfo = sendPayload(np.getPayload()); np.setPayloadTransferInfo(transferInfo); } + np.encrypt(key); + session.write(np.serialize()); + return true; } catch (Exception e) { e.printStackTrace(); diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java index f44cfa01..5cd57e80 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java @@ -65,10 +65,14 @@ public class LanLinkProvider extends BaseLinkProvider { LanLink prevLink = nioSessions.get(session.getId()); if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { + String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId"); if (np.getString("deviceId").equals(myId)) { return; } + + //Log.e("LanLinkProvider", "Identity package received from "+np.getString("deviceName")); + LanLink link = new LanLink(session, np.getString("deviceId"), LanLinkProvider.this); nioSessions.put(session.getId(),link); addLink(np, link); @@ -90,70 +94,59 @@ public class LanLinkProvider extends BaseLinkProvider { //Log.e("LanLinkProvider", "Udp message received (" + message.getClass() + ") " + message.toString()); - NetworkPackage np = null; - try { //We should receive a string thanks to the TextLineCodecFactory filter String theMessage = (String) message; - np = NetworkPackage.unserialize(theMessage); - } catch (Exception e) { - e.printStackTrace(); - Log.e("LanLinkProvider", "Could not unserialize package"); - } + final NetworkPackage identityPackage = NetworkPackage.unserialize(theMessage); - if (np != null) { - - final NetworkPackage identityPackage = np; - if (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { + if (!identityPackage.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { Log.e("LanLinkProvider", "1 Expecting an identity package"); return; } else { String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId"); - if (np.getString("deviceId").equals(myId)) { + if (identityPackage.getString("deviceId").equals(myId)) { return; } } Log.i("LanLinkProvider", "Identity package received, creating link"); - try { - final InetSocketAddress address = (InetSocketAddress) udpSession.getRemoteAddress(); + final InetSocketAddress address = (InetSocketAddress) udpSession.getRemoteAddress(); - final NioSocketConnector connector = new NioSocketConnector(); - connector.setHandler(tcpHandler); - //TextLineCodecFactory will split incoming data delimited by the given string - connector.getFilterChain().addLast("codec", - new ProtocolCodecFilter( - new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX) - ) - ); - connector.getSessionConfig().setKeepAlive(true); + final NioSocketConnector connector = new NioSocketConnector(); + connector.setHandler(tcpHandler); + //TextLineCodecFactory will split incoming data delimited by the given string + connector.getFilterChain().addLast("codec", + new ProtocolCodecFilter( + new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX) + ) + ); + connector.getSessionConfig().setKeepAlive(true); - int tcpPort = np.getInt("tcpPort",port); - ConnectFuture future = connector.connect(new InetSocketAddress(address.getAddress(), tcpPort)); - future.addListener(new IoFutureListener() { - @Override - public void operationComplete(IoFuture ioFuture) { - IoSession session = ioFuture.getSession(); + int tcpPort = identityPackage.getInt("tcpPort",port); + ConnectFuture future = connector.connect(new InetSocketAddress(address.getAddress(), tcpPort)); + future.addListener(new IoFutureListener() { + @Override + public void operationComplete(IoFuture ioFuture) { + IoSession session = ioFuture.getSession(); - Log.i("LanLinkProvider", "Connection successful: " + session.isConnected()); + Log.i("LanLinkProvider", "Connection successful: " + session.isConnected()); - LanLink link = new LanLink(session, identityPackage.getString("deviceId"), LanLinkProvider.this); + LanLink link = new LanLink(session, identityPackage.getString("deviceId"), LanLinkProvider.this); - NetworkPackage np2 = NetworkPackage.createIdentityPackage(context); - link.sendPackage(np2); + NetworkPackage np2 = NetworkPackage.createIdentityPackage(context); + link.sendPackage(np2); - nioSessions.put(session.getId(), link); - addLink(identityPackage, link); - } - }); - - } catch (Exception e) { - Log.e("LanLinkProvider","Exception!!"); - e.printStackTrace(); - } + nioSessions.put(session.getId(), link); + addLink(identityPackage, link); + } + }); + } catch (Exception e) { + Log.e("LanLinkProvider","Exception receiving udp package!!"); + e.printStackTrace(); } + } }; diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java b/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java index 0ea450d6..d32d3758 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/Device.java @@ -419,30 +419,34 @@ public class Device implements BaseLink.PackageReceiver { public boolean sendPackage(final NetworkPackage np) { - new AsyncTask() { + new Thread(new Runnable() { @Override - protected Void doInBackground(Void... voids) { + public void run() { boolean useEncryption = (!np.getType().equals(NetworkPackage.PACKAGE_TYPE_PAIR) && isPaired()); + //Log.e("sendPackage", "Sending..."); + for(BaseLink link : links) { if (useEncryption) { - if (link.sendPackageEncrypted(np, publicKey)) return null; + if (link.sendPackageEncrypted(np, publicKey)) { + //Log.e("sendPackage", "Sent"); + return; + } } else { - if (link.sendPackage(np)) return null; + if (link.sendPackage(np)) { + //Log.e("sendPackage", "Sent"); + return; + } } } Log.e("sendPackage","Error: Package could not be sent ("+links.size()+" links available)"); - return null; - } - }.execute(); - - //TODO: Detect when unable to send a package and try again somehow + }).start(); return !links.isEmpty(); } diff --git a/KdeConnect/src/main/java/org/kde/kdeconnect/NetworkPackage.java b/KdeConnect/src/main/java/org/kde/kdeconnect/NetworkPackage.java index 49e342a6..a2240cec 100644 --- a/KdeConnect/src/main/java/org/kde/kdeconnect/NetworkPackage.java +++ b/KdeConnect/src/main/java/org/kde/kdeconnect/NetworkPackage.java @@ -150,7 +150,7 @@ public class NetworkPackage { } } catch (Exception e) { e.printStackTrace(); - Log.e("NetworkPackage", "Unserialization exception"); + Log.e("NetworkPackage", "Unserialization exception unserializing "+s); return null; } diff --git a/kdeconnect-android.iml b/kdeconnect-android.iml index c2318111..94f1c61c 100644 --- a/kdeconnect-android.iml +++ b/kdeconnect-android.iml @@ -1,5 +1,5 @@ - +