mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 09:58:08 +00:00
Fix discovering myself and too many registrations
This commit is contained in:
parent
826c0a854e
commit
ad49e500fa
@ -53,6 +53,7 @@ import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -61,7 +62,7 @@ import javax.net.SocketFactory;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
/**
|
||||
* This BaseLinkProvider creates {@link MulticastLink}s to other devices on the same
|
||||
* This MulticastLinkProvider creates {@link MulticastLink}s to other devices on the same
|
||||
* WiFi network. The first packet sent over a socket must be an
|
||||
* {@link NetworkPacket#createIdentityPacket(Context)}.
|
||||
*
|
||||
@ -73,24 +74,19 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
|
||||
static final String SERVICE_TYPE = "_kdeconnect._tcp";
|
||||
|
||||
private NsdManager mNsdManager;
|
||||
private RegistrationListener mRegistrationListener;
|
||||
private boolean mServiceRegistered = false;
|
||||
|
||||
private final static int MIN_PORT = 1716;
|
||||
private final static int MAX_PORT = 1764;
|
||||
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
|
||||
|
||||
private final Context context;
|
||||
|
||||
private final HashMap<String, MulticastLink> visibleComputers = new HashMap<>(); //Links by device id
|
||||
|
||||
private NsdManager mNsdManager;
|
||||
private RegistrationListener mRegistrationListener;
|
||||
private NsdManager.DiscoveryListener discoveryListener;
|
||||
private ServerSocket tcpServer;
|
||||
|
||||
private boolean listening = false;
|
||||
|
||||
// To prevent infinte loop between Android < IceCream because both device can only broadcast identity package but cannot connect via TCP
|
||||
private final ArrayList<InetAddress> reverseConnectionBlackList = new ArrayList<>();
|
||||
private final HashMap<String, MulticastLink> visibleComputers = new HashMap<>(); //Links by device id
|
||||
|
||||
@Override // SocketClosedCallback
|
||||
public void linkDisconnected(MulticastLink brokenLink) {
|
||||
@ -256,8 +252,8 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
String message = reader.readLine();
|
||||
Log.e("TcpListener","Received TCP package: "+message);
|
||||
return NetworkPacket.unserialize(message);
|
||||
//Log.e("TcpListener","Received TCP package: "+networkPacket.serialize());
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Exception while receiving TCP packet", e);
|
||||
return null;
|
||||
@ -314,7 +310,7 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
// Save the service name. Android may have changed it in order to
|
||||
// resolve a conflict, so update the name you initially requested
|
||||
// with the name Android actually used.
|
||||
Log.i(LOG_TAG, "Registered " + NsdServiceInfo.getServiceName());
|
||||
Log.e(LOG_TAG, "Registered " + NsdServiceInfo.getServiceName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -327,7 +323,7 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
public void onServiceUnregistered(NsdServiceInfo arg0) {
|
||||
// Service has been unregistered. This only happens when you call
|
||||
// NsdManager.unregisterService() and pass in this listener.
|
||||
Log.w(LOG_TAG, "Service unregistered: " + arg0);
|
||||
Log.e(LOG_TAG, "Service unregistered: " + arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -339,43 +335,35 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public void initializeNsdManager(RegistrationListener registrationListener) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return;
|
||||
}
|
||||
public void initializeNsdManager() {
|
||||
|
||||
mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
|
||||
try {
|
||||
mNsdManager.unregisterService(registrationListener);
|
||||
} catch (java.lang.IllegalArgumentException e) {
|
||||
// not yet registered, but it's fine.
|
||||
}
|
||||
|
||||
NsdServiceInfo serviceInfo = new NsdServiceInfo();
|
||||
|
||||
// It wasn't possible for the device which receives the incoming connection
|
||||
// to use these attributes (there's no way to correlate the incoming connection
|
||||
// with a discovered service), so we have to rely on sending this stuff in
|
||||
// an identity packet like in the LanLink. That's the reason this is commented out.
|
||||
// These cause the requirement for api level 21.
|
||||
serviceInfo.setAttribute("id", DeviceHelper.getDeviceId(context));
|
||||
// The name is subject to change based on conflicts
|
||||
// with other services advertised on the same network.
|
||||
NetworkPacket myIdentity = NetworkPacket.createIdentityPacket(context);
|
||||
String did = myIdentity.getString("deviceID");
|
||||
String name = myIdentity.getString("deviceName");
|
||||
InetAddress addr = this.tcpServer.getInetAddress();
|
||||
int port = this.tcpServer.getLocalPort();
|
||||
|
||||
// These cause the requirement for api level 21.
|
||||
serviceInfo.setAttribute("name", myIdentity.getString("deviceName"));
|
||||
serviceInfo.setAttribute("id", myIdentity.getString("deviceId"));
|
||||
serviceInfo.setAttribute("type", myIdentity.getString("deviceType"));
|
||||
serviceInfo.setAttribute("version", myIdentity.getString("protocolVersion"));
|
||||
|
||||
//serviceInfo.setAttribute("name", DeviceHelper.getDeviceName(context));
|
||||
//serviceInfo.setAttribute("type", DeviceHelper.getDeviceType(context).toString());
|
||||
//serviceInfo.setAttribute("version", Integer.toString(DeviceHelper.ProtocolVersion));
|
||||
// It might be nice to add the capabilities in the mDNS advertisement too, but without
|
||||
// some kind of encoding that is too large for the TXT record
|
||||
|
||||
serviceInfo.setServiceName("KDE Connect on " + myIdentity.getString("deviceName"));
|
||||
serviceInfo.setServiceName("KDE Connect on " + DeviceHelper.getDeviceName(context));
|
||||
serviceInfo.setServiceType(SERVICE_TYPE);
|
||||
serviceInfo.setHost(addr);
|
||||
serviceInfo.setPort(port);
|
||||
// This gets autodetected if not set
|
||||
//serviceInfo.setHost(this.tcpServer.getInetAddress());
|
||||
serviceInfo.setPort(this.tcpServer.getLocalPort());
|
||||
|
||||
//Log.d("KDE/Lan", "service: " + serviceInfo.toString());
|
||||
|
||||
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
|
||||
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
@ -389,7 +377,13 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
|
||||
@Override
|
||||
public void onServiceResolved(NsdServiceInfo serviceInfo) {
|
||||
Log.i(LOG_TAG, "Successfully resolved " + serviceInfo);
|
||||
Log.e(LOG_TAG, "Successfully resolved " + serviceInfo);
|
||||
|
||||
byte[] id = serviceInfo.getAttributes().get("id");
|
||||
if (id != null && DeviceHelper.getDeviceId(context).equals(new String(id, StandardCharsets.UTF_8))) {
|
||||
Log.e(LOG_TAG, "Ignoring connection to myself");
|
||||
return;
|
||||
}
|
||||
|
||||
InetAddress hostname = serviceInfo.getHost();
|
||||
int remotePort = serviceInfo.getPort();
|
||||
@ -408,8 +402,8 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
|
||||
try {
|
||||
Log.i(LOG_TAG, "Got identity: " + otherIdentity.serialize());
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, "Got identity, but unable to serialize!", e);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Got identity, but unable to serialize from " + serviceInfo, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -419,7 +413,7 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public void initializeDiscoveryListener() {
|
||||
// Instantiate a new DiscoveryListener
|
||||
NsdManager.DiscoveryListener discoveryListener = new NsdManager.DiscoveryListener() {
|
||||
discoveryListener = new NsdManager.DiscoveryListener() {
|
||||
|
||||
// Called as soon as service discovery begins.
|
||||
@Override
|
||||
@ -430,7 +424,7 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
@Override
|
||||
public void onServiceFound(NsdServiceInfo service) {
|
||||
// A service was found! Do something with it.
|
||||
Log.d(LOG_TAG, "Service discovery success" + service);
|
||||
Log.e(LOG_TAG, "Service discovery success" + service);
|
||||
mNsdManager.resolveService(service, createResolveListener());
|
||||
}
|
||||
|
||||
@ -443,7 +437,7 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
|
||||
@Override
|
||||
public void onDiscoveryStopped(String serviceType) {
|
||||
Log.i(LOG_TAG, "Discovery stopped: " + serviceType);
|
||||
Log.e(LOG_TAG, "Discovery stopped: " + serviceType);
|
||||
listening = false;
|
||||
}
|
||||
|
||||
@ -463,28 +457,6 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
Log.i(LOG_TAG, "MulticastBackend not supported on devices older thab Lollipop");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!listening) {
|
||||
listening = true;
|
||||
|
||||
// Need to set up TCP before setting up mDNS because we need to know the TCP listening
|
||||
// address and port
|
||||
setupTcpListener();
|
||||
|
||||
initializeRegistrationListener();
|
||||
|
||||
initializeNsdManager(mRegistrationListener);
|
||||
|
||||
initializeDiscoveryListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNetworkChange() {
|
||||
onStop();
|
||||
@ -492,15 +464,27 @@ public class MulticastLinkProvider extends BaseLinkProvider implements Multicast
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
// This backend does not work on older Android versions
|
||||
return;
|
||||
}
|
||||
public synchronized void onStart() {
|
||||
if (!listening) {
|
||||
listening = true;
|
||||
|
||||
mNsdManager.unregisterService(mRegistrationListener);
|
||||
tcpServer.close();
|
||||
listening = false;
|
||||
// Need to set up TCP before setting up mDNS because we need to know the TCP listening
|
||||
// address and port
|
||||
setupTcpListener();
|
||||
initializeRegistrationListener();
|
||||
initializeNsdManager();
|
||||
initializeDiscoveryListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onStop() {
|
||||
//if (listening) {
|
||||
// mNsdManager.stopServiceDiscovery(discoveryListener);
|
||||
// mNsdManager.unregisterService(mRegistrationListener);
|
||||
// try { tcpServer.close(); } catch (IOException ignored) { }
|
||||
// listening = false;
|
||||
//}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -163,7 +163,7 @@ public class BackgroundService extends Service {
|
||||
}
|
||||
|
||||
private void registerLinkProviders() {
|
||||
linkProviders.add(new LanLinkProvider(this));
|
||||
//linkProviders.add(new LanLinkProvider(this));
|
||||
linkProviders.add(new MulticastLinkProvider(this));
|
||||
// linkProviders.add(new LoopbackLinkProvider(this));
|
||||
// linkProviders.add(new BluetoothLinkProvider(this));
|
||||
|
Loading…
x
Reference in New Issue
Block a user