2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-31 14:15:14 +00:00

Fixed NioSocketConnector being kept open after every connection received

And other fixes in the LanLinkProvider
This commit is contained in:
Albert Vaca
2015-04-04 12:55:52 -07:00
parent a0b82d17b4
commit cc17402609

View File

@@ -21,7 +21,6 @@
package org.kde.kdeconnect.Backends.LanBackend; package org.kde.kdeconnect.Backends.LanBackend;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.util.LongSparseArray; import android.support.v4.util.LongSparseArray;
import android.util.Log; import android.util.Log;
@@ -59,6 +58,7 @@ public class LanLinkProvider extends BaseLinkProvider {
private final Context context; private final Context context;
private final HashMap<String, LanLink> visibleComputers = new HashMap<String, LanLink>(); private final HashMap<String, LanLink> visibleComputers = new HashMap<String, LanLink>();
private final LongSparseArray<LanLink> nioSessions = new LongSparseArray<LanLink>(); private final LongSparseArray<LanLink> nioSessions = new LongSparseArray<LanLink>();
private final LongSparseArray<NioSocketConnector> nioConnectors = new LongSparseArray<NioSocketConnector>();
private NioSocketAcceptor tcpAcceptor = null; private NioSocketAcceptor tcpAcceptor = null;
private NioDatagramAcceptor udpAcceptor = null; private NioDatagramAcceptor udpAcceptor = null;
@@ -66,29 +66,46 @@ public class LanLinkProvider extends BaseLinkProvider {
private final IoHandler tcpHandler = new IoHandlerAdapter() { private final IoHandler tcpHandler = new IoHandlerAdapter() {
@Override @Override
public void sessionClosed(IoSession session) throws Exception { public void sessionClosed(IoSession session) throws Exception {
try {
final LanLink brokenLink = nioSessions.get(session.getId()); long id = session.getId();
if (brokenLink != null) { final LanLink brokenLink = nioSessions.get(id);
nioSessions.remove(session.getId()); NioSocketConnector connector = nioConnectors.get(id);
brokenLink.disconnect(); if (connector != null) {
String deviceId = brokenLink.getDeviceId(); connector.dispose();
if (visibleComputers.get(deviceId) == brokenLink) { nioConnectors.remove(id);
visibleComputers.remove(deviceId);
} }
new Thread(new Runnable() { if (brokenLink != null) {
@Override nioSessions.remove(id);
public void run() { //Log.i("KDE/LanLinkProvider", "nioSessions.size(): " + nioSessions.size() + " (-)");
//Wait a bit before emiting connectionLost, in case the same device re-appears try {
try { brokenLink.disconnect();
Thread.sleep(200); } catch (Exception e) {
} catch (InterruptedException e) { } e.printStackTrace();
connectionLost(brokenLink); Log.e("KDE/LanLinkProvider", "Exception. Already disconnected?");
} }
}).start(); //Log.i("KDE/LanLinkProvider", "Disconnected!");
String deviceId = brokenLink.getDeviceId();
if (visibleComputers.get(deviceId) == brokenLink) {
visibleComputers.remove(deviceId);
}
new Thread(new Runnable() {
@Override
public void run() {
//Wait a bit before emiting connectionLost, in case the same device re-appears
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
connectionLost(brokenLink);
}
}).start();
}
} catch (Exception e) { //If we don't catch it here, Mina will swallow it :/
e.printStackTrace();
Log.e("KDE/LanLinkProvider", "sessionClosed exception");
} }
} }
@Override @Override
@@ -166,36 +183,43 @@ public class LanLinkProvider extends BaseLinkProvider {
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory)); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory));
int tcpPort = identityPackage.getInt("tcpPort",port); int tcpPort = identityPackage.getInt("tcpPort",port);
ConnectFuture future = connector.connect(new InetSocketAddress(address.getAddress(), tcpPort)); final ConnectFuture future = connector.connect(new InetSocketAddress(address.getAddress(), tcpPort));
future.addListener(new IoFutureListener<IoFuture>() { future.addListener(new IoFutureListener<IoFuture>() {
@Override @Override
public void operationComplete(IoFuture ioFuture) { public void operationComplete(IoFuture ioFuture) {
final IoSession session = ioFuture.getSession(); try {
future.removeListener(this);
final IoSession session = ioFuture.getSession();
final LanLink link = new LanLink(session, identityPackage.getString("deviceId"), LanLinkProvider.this);
final LanLink link = new LanLink(session, identityPackage.getString("deviceId"), LanLinkProvider.this); //Log.i("KDE/LanLinkProvider", "Connection successful: " + session.isConnected());
Log.i("LanLinkProvider", "Connection successful: " + session.isConnected()); new Thread(new Runnable() {
@Override
public void run() {
NetworkPackage np2 = NetworkPackage.createIdentityPackage(context);
link.sendPackage(np2,new Device.SendPackageStatusCallback() {
@Override
protected void onSuccess() {
nioSessions.put(session.getId(), link);
nioConnectors.put(session.getId(), connector);
//Log.e("KDE/LanLinkProvider","nioSessions.size(): " + nioSessions.size());
addLink(identityPackage, link);
}
new Thread(new Runnable() { @Override
@Override protected void onFailure(Throwable e) {
public void run() { Log.e("KDE/LanLinkProvider", "Connection failed: could not send identity package back");
NetworkPackage np2 = NetworkPackage.createIdentityPackage(context); }
link.sendPackage(np2,new Device.SendPackageStatusCallback() { });
@Override
protected void onSuccess() {
nioSessions.put(session.getId(), link);
addLink(identityPackage, link);
}
@Override
protected void onFailure(Throwable e) {
}
});
}
}).start();
}
}).start();
} catch (Exception e) { //If we don't catch it here, Mina will swallow it :/
e.printStackTrace();
Log.e("KDE/LanLinkProvider", "sessionClosed exception");
}
} }
}); });
@@ -233,13 +257,11 @@ public class LanLinkProvider extends BaseLinkProvider {
tcpAcceptor.setHandler(tcpHandler); tcpAcceptor.setHandler(tcpHandler);
tcpAcceptor.getSessionConfig().setKeepAlive(true); tcpAcceptor.getSessionConfig().setKeepAlive(true);
tcpAcceptor.getSessionConfig().setReuseAddress(true); tcpAcceptor.getSessionConfig().setReuseAddress(true);
tcpAcceptor.setCloseOnDeactivation(false);
//TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n //TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n
TextLineCodecFactory textLineFactory = new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX); TextLineCodecFactory textLineFactory = new TextLineCodecFactory(Charset.defaultCharset(), LineDelimiter.UNIX, LineDelimiter.UNIX);
textLineFactory.setDecoderMaxLineLength(512*1024); //Allow to receive up to 512kb of data textLineFactory.setDecoderMaxLineLength(512*1024); //Allow to receive up to 512kb of data
tcpAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory)); tcpAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(textLineFactory));
udpAcceptor = new NioDatagramAcceptor(); udpAcceptor = new NioDatagramAcceptor();
udpAcceptor.getSessionConfig().setReuseAddress(true); //Share port if existing udpAcceptor.getSessionConfig().setReuseAddress(true); //Share port if existing
//TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n //TextLineCodecFactory will buffer incoming data and emit a message very time it finds a \n
@@ -281,26 +303,36 @@ public class LanLinkProvider extends BaseLinkProvider {
//I'm on a new network, let's be polite and introduce myself //I'm on a new network, let's be polite and introduce myself
final int finalTcpPort = tcpPort; final int finalTcpPort = tcpPort;
new AsyncTask<Void,Void,Void>() { new Thread(new Runnable() {
@Override @Override
protected Void doInBackground(Void... voids) { public void run() {
String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString( String deviceListPrefs = PreferenceManager.getDefaultSharedPreferences(context).getString(
KEY_CUSTOM_DEVLIST_PREFERENCE, ""); KEY_CUSTOM_DEVLIST_PREFERENCE, "");
ArrayList<String> iplist = new ArrayList<String>(); ArrayList<String> iplist = new ArrayList<String>();
if (!deviceListPrefs.isEmpty()) { if (!deviceListPrefs.isEmpty()) {
iplist = CustomDevicesActivity.deserializeIpList(deviceListPrefs); iplist = CustomDevicesActivity.deserializeIpList(deviceListPrefs);
} }
iplist.add("255.255.255.255"); iplist.add("255.255.255.255"); //Default: broadcast.
NetworkPackage identity = NetworkPackage.createIdentityPackage(context);
identity.set("tcpPort", finalTcpPort);
DatagramSocket socket = null;
byte[] bytes = null;
try {
socket = new DatagramSocket();
socket.setReuseAddress(true);
socket.setBroadcast(true);
bytes = identity.serialize().getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
Log.e("KDE/LanLinkProvider","Failed to create DatagramSocket");
}
//Log.e("KDE/LanLinkProvider","Sending packet to "+iplist.size()+" ips");
for (String ipstr : iplist) { for (String ipstr : iplist) {
try { try {
InetAddress client = InetAddress.getByName(ipstr); InetAddress client = InetAddress.getByName(ipstr);
NetworkPackage identity = NetworkPackage.createIdentityPackage(context); DatagramPacket packet = new DatagramPacket(bytes, bytes.length, client, port);
identity.set("tcpPort", finalTcpPort);
byte[] b = identity.serialize().getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(b, b.length, client, port);
DatagramSocket socket = new DatagramSocket();
socket.setReuseAddress(true);
socket.setBroadcast(true);
socket.send(packet); socket.send(packet);
//Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+packet.getAddress()); //Log.i("KDE/LanLinkProvider","Udp identity package sent to address "+packet.getAddress());
} catch(Exception e) { } catch(Exception e) {
@@ -308,13 +340,10 @@ public class LanLinkProvider extends BaseLinkProvider {
Log.e("KDE/LanLinkProvider","Sending udp identity package failed. Invalid address? ("+ipstr+")"); Log.e("KDE/LanLinkProvider","Sending udp identity package failed. Invalid address? ("+ipstr+")");
} }
} }
socket.close();
return null;
} }
}).start();
}.execute();
} }
@Override @Override
@@ -332,14 +361,12 @@ public class LanLinkProvider extends BaseLinkProvider {
udpAcceptor.unbind(); udpAcceptor.unbind();
tcpAcceptor.unbind(); tcpAcceptor.unbind();
} }
/*
@Override
public int getPriority() {
return 1000;
}
*/
@Override @Override
public String getName() { public String getName() {
return "LanLinkProvider"; return "LanLinkProvider";
} }
} }