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:
@@ -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";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user