2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-30 13:47:41 +00:00

Partially revert "Add MDNS discovery"

This partially reverts commit 8f8a09a99a.

Removing MDNS to do one last bugfix-only release.
This commit is contained in:
Albert Vaca Cintora
2023-09-07 08:37:35 +02:00
parent 3fbef1da87
commit 5da804939d
5 changed files with 4 additions and 344 deletions

View File

@@ -549,8 +549,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="plugin_stats">Plugin stats</string> <string name="plugin_stats">Plugin stats</string>
<string name="enable_udp_broadcast">Enable UDP device discovery</string>
<string name="receive_notifications_permission_explanation">Notifications need to be allowed to receive them from other devices</string> <string name="receive_notifications_permission_explanation">Notifications need to be allowed to receive them from other devices</string>
<string name="findmyphone_notifications_explanation">The notifications permission is needed so the phone can ring when the app is in the background</string> <string name="findmyphone_notifications_explanation">The notifications permission is needed so the phone can ring when the app is in the background</string>
<string name="no_notifications">Notifications are disabled, you won\'t receive incoming pair notifications.</string> <string name="no_notifications">Notifications are disabled, you won\'t receive incoming pair notifications.</string>

View File

@@ -28,7 +28,6 @@ import org.kde.kdeconnect.Helpers.TrustedNetworkHelper;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.UserInterface.CustomDevicesActivity; import org.kde.kdeconnect.UserInterface.CustomDevicesActivity;
import org.kde.kdeconnect.UserInterface.SettingsFragment;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@@ -62,9 +61,9 @@ import kotlin.text.Charsets;
*/ */
public class LanLinkProvider extends BaseLinkProvider { public class LanLinkProvider extends BaseLinkProvider {
final static int UDP_PORT = 1716; private final static int UDP_PORT = 1716;
final static int MIN_PORT = 1716; private final static int MIN_PORT = 1716;
final static int MAX_PORT = 1764; private final static int MAX_PORT = 1764;
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739; final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
final static int MAX_UDP_PACKET_SIZE = 1024 * 512; final static int MAX_UDP_PACKET_SIZE = 1024 * 512;
@@ -73,15 +72,13 @@ public class LanLinkProvider extends BaseLinkProvider {
private final Context context; private final Context context;
final HashMap<String, LanLink> visibleDevices = new HashMap<>(); //Links by device id private final HashMap<String, LanLink> visibleDevices = new HashMap<>(); // Links by device id
final ConcurrentHashMap<String, Long> lastConnectionTime = new ConcurrentHashMap<>(); final ConcurrentHashMap<String, Long> lastConnectionTime = new ConcurrentHashMap<>();
private ServerSocket tcpServer; private ServerSocket tcpServer;
private DatagramSocket udpServer; private DatagramSocket udpServer;
private MdnsDiscovery mdnsDiscovery;
private long lastBroadcast = 0; private long lastBroadcast = 0;
private final static long delayBetweenBroadcasts = 200; private final static long delayBetweenBroadcasts = 200;
@@ -271,7 +268,6 @@ public class LanLinkProvider extends BaseLinkProvider {
public LanLinkProvider(Context context) { public LanLinkProvider(Context context) {
this.context = context; this.context = context;
this.mdnsDiscovery = new MdnsDiscovery(context, this);
} }
private void setupUdpListener() { private void setupUdpListener() {
@@ -359,11 +355,6 @@ public class LanLinkProvider extends BaseLinkProvider {
} }
private void broadcastUdpIdentityPacket(@Nullable Network network) { private void broadcastUdpIdentityPacket(@Nullable Network network) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(SettingsFragment.KEY_UDP_BROADCAST_ENABLED, true)) {
Log.i("LanLinkProvider", "UDP broadcast is disabled in settings. Skipping.");
return;
}
ThreadHelper.execute(() -> { ThreadHelper.execute(() -> {
List<String> ipStringList = CustomDevicesActivity List<String> ipStringList = CustomDevicesActivity
@@ -451,9 +442,6 @@ public class LanLinkProvider extends BaseLinkProvider {
setupUdpListener(); setupUdpListener();
setupTcpListener(); setupTcpListener();
mdnsDiscovery.startDiscovering();
mdnsDiscovery.startAnnouncing();
broadcastUdpIdentityPacket(null); broadcastUdpIdentityPacket(null);
} }
} }
@@ -467,16 +455,12 @@ public class LanLinkProvider extends BaseLinkProvider {
lastBroadcast = System.currentTimeMillis(); lastBroadcast = System.currentTimeMillis();
broadcastUdpIdentityPacket(network); broadcastUdpIdentityPacket(network);
mdnsDiscovery.stopDiscovering();
mdnsDiscovery.startDiscovering();
} }
@Override @Override
public void onStop() { public void onStop() {
//Log.i("KDE/LanLinkProvider", "onStop"); //Log.i("KDE/LanLinkProvider", "onStop");
listening = false; listening = false;
mdnsDiscovery.stopAnnouncing();
mdnsDiscovery.stopDiscovering();
try { try {
tcpServer.close(); tcpServer.close();
} catch (Exception e) { } catch (Exception e) {

View File

@@ -1,224 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.Backends.LanBackend;
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.net.wifi.WifiManager;
import android.util.Log;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import java.net.InetAddress;
import java.util.Collections;
public class MdnsDiscovery {
static final String LOG_TAG = "MdnsDiscovery";
static final String SERVICE_TYPE = "_kdeconnect._udp";
private final Context context;
private final LanLinkProvider lanLinkProvider;
private final NsdManager mNsdManager;
private NsdManager.RegistrationListener registrationListener;
private NsdManager.DiscoveryListener discoveryListener;
private WifiManager.MulticastLock multicastLock;
private NsdResolveQueue mNsdResolveQueue;
public MdnsDiscovery(Context context, LanLinkProvider lanLinkProvider) {
this.context = context;
this.lanLinkProvider = lanLinkProvider;
this.mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
this.mNsdResolveQueue = new NsdResolveQueue(this.mNsdManager);
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
multicastLock = wifiManager.createMulticastLock("kdeConnectMdnsMulticastLock");
}
void startDiscovering() {
if (discoveryListener == null) {
multicastLock.acquire();
discoveryListener = createDiscoveryListener();
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener);
}
}
void stopDiscovering() {
try {
if (discoveryListener != null) {
mNsdManager.stopServiceDiscovery(discoveryListener);
multicastLock.release();
}
} catch(IllegalArgumentException e) {
// Ignore "listener not registered" exception
}
discoveryListener = null;
}
void stopAnnouncing() {
try {
if (registrationListener != null) {
mNsdManager.unregisterService(registrationListener);
}
} catch(IllegalArgumentException e) {
// Ignore "listener not registered" exception
}
registrationListener = null;
}
void startAnnouncing() {
if (registrationListener == null) {
NsdServiceInfo serviceInfo;
try {
serviceInfo = createNsdServiceInfo();
} catch (IllegalAccessException e) {
Log.w(LOG_TAG, "Couldn't start announcing via MDNS: " + e.getMessage());
return;
}
registrationListener = createRegistrationListener();
mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener);
}
}
NsdManager.RegistrationListener createRegistrationListener() {
return new NsdManager.RegistrationListener() {
@Override
public void onServiceRegistered(NsdServiceInfo serviceInfo) {
// If Android changed the service name to avoid conflicts, here we can read it.
Log.i(LOG_TAG, "Registered " + serviceInfo.getServiceName());
}
@Override
public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(LOG_TAG, "Registration failed with: " + errorCode);
}
@Override
public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
Log.d(LOG_TAG, "Service unregistered: " + serviceInfo);
}
@Override
public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(LOG_TAG, "Unregister of " + serviceInfo + " failed with: " + errorCode);
}
};
}
public NsdServiceInfo createNsdServiceInfo() throws IllegalAccessException {
NsdServiceInfo serviceInfo = new NsdServiceInfo();
String deviceId = DeviceHelper.getDeviceId(context);
// Without resolving the DNS, the service name is the only info we have so it must be sufficient to identify a device.
// Also, it must be unique, otherwise it will be automatically renamed. For these reasons we use the deviceId.
serviceInfo.setServiceName(deviceId);
serviceInfo.setServiceType(SERVICE_TYPE);
serviceInfo.setPort(LanLinkProvider.UDP_PORT);
// The following fields aren't really used for anything, since we can't include enough info
// for it to be useful (namely: we can't include the device certificate).
// Each field (key + value) needs to be < 255 bytes. All the fields combined need to be < 1300 bytes.
// Also, on Android Lollipop those fields aren't resolved.
String deviceName = DeviceHelper.getDeviceName(context);
String deviceType = DeviceHelper.getDeviceType(context).toString();
String protocolVersion = Integer.toString(DeviceHelper.ProtocolVersion);
serviceInfo.setAttribute("id", deviceId);
serviceInfo.setAttribute("name", deviceName);
serviceInfo.setAttribute("type", deviceType);
serviceInfo.setAttribute("protocol", protocolVersion);
Log.i(LOG_TAG, "My MDNS info: " + serviceInfo);
return serviceInfo;
}
NsdManager.DiscoveryListener createDiscoveryListener() {
return new NsdManager.DiscoveryListener() {
final String myId = DeviceHelper.getDeviceId(context);
@Override
public void onDiscoveryStarted(String serviceType) {
Log.i(LOG_TAG, "Service discovery started: " + serviceType);
}
@Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
Log.d(LOG_TAG, "Service discovered: " + serviceInfo);
String deviceId = serviceInfo.getServiceName();
if (myId.equals(deviceId)) {
Log.d(LOG_TAG, "Discovered myself, ignoring.");
return;
}
if (lanLinkProvider.visibleDevices.containsKey(deviceId)) {
Log.i(LOG_TAG, "MDNS discovered " + deviceId + " to which I'm already connected to. Ignoring.");
return;
}
// We use a queue because only one service can be resolved at
// a time, otherwise we get error 3 (already active) in onResolveFailed.
mNsdResolveQueue.resolveOrEnqueue(serviceInfo, createResolveListener());
}
@Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
Log.w(LOG_TAG, "Service lost: " + serviceInfo);
// We can't see this device via mdns. This probably means it's not reachable anymore
// but we do nothing here since we have other ways to do detect unreachable devices
// that hopefully will also trigger.
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.i(LOG_TAG, "MDNS discovery stopped: " + serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(LOG_TAG, "MDNS discovery start failed: " + errorCode);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(LOG_TAG, "MDNS discovery stop failed: " + errorCode);
}
};
}
/**
* Returns a new listener instance since NsdManager wants a different listener each time you call resolveService
*/
NsdManager.ResolveListener createResolveListener() {
return new NsdManager.ResolveListener() {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.w(LOG_TAG, "MDNS error " + errorCode + " resolving service: " + serviceInfo);
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.i(LOG_TAG, "MDNS successfully resolved " + serviceInfo);
// Let the LanLinkProvider handle the connection
InetAddress remoteAddress = serviceInfo.getHost();
lanLinkProvider.sendUdpIdentityPacket(Collections.singletonList(remoteAddress), null);
}
};
}
}

View File

@@ -1,91 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.Backends.LanBackend;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.util.Log;
import androidx.annotation.NonNull;
import java.util.LinkedList;
public class NsdResolveQueue {
static final String LOG_TAG = "NsdResolveQueue";
final @NonNull NsdManager mNsdManager;
private final Object mLock = new Object();
private final LinkedList<PendingResolve> mResolveRequests = new LinkedList<>();
public NsdResolveQueue(NsdManager nsdManager) {
this.mNsdManager = nsdManager;
}
private static class PendingResolve {
final @NonNull NsdServiceInfo serviceInfo;
final @NonNull NsdManager.ResolveListener listener;
private PendingResolve(@NonNull NsdServiceInfo serviceInfo, @NonNull NsdManager.ResolveListener listener) {
this.serviceInfo = serviceInfo;
this.listener = listener;
}
}
public void resolveOrEnqueue(@NonNull NsdServiceInfo serviceInfo, @NonNull NsdManager.ResolveListener listener) {
synchronized (mLock) {
for (PendingResolve existing : mResolveRequests) {
if (serviceInfo.getServiceName().equals(existing.serviceInfo.getServiceName())) {
Log.i(LOG_TAG, "Not enqueuing a new resolve request for the same service: " + serviceInfo.getServiceName());
return;
}
}
mResolveRequests.addLast(new PendingResolve(serviceInfo, new ListenerWrapper(listener)));
if (mResolveRequests.size() == 1) {
resolveNextRequest();
}
}
}
private class ListenerWrapper implements NsdManager.ResolveListener {
private final @NonNull NsdManager.ResolveListener mListener;
private ListenerWrapper(@NonNull NsdManager.ResolveListener listener) {
mListener = listener;
}
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
mListener.onResolveFailed(serviceInfo, errorCode);
synchronized (mLock) {
mResolveRequests.pop();
resolveNextRequest();
}
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
mListener.onServiceResolved(serviceInfo);
synchronized (mLock) {
mResolveRequests.pop();
resolveNextRequest();
}
}
}
private void resolveNextRequest() {
if (!mResolveRequests.isEmpty()) {
PendingResolve request = mResolveRequests.getFirst();
mNsdManager.resolveService(request.serviceInfo, request.listener);
}
}
}

View File

@@ -37,7 +37,6 @@ import org.kde.kdeconnect_tp.R;
public class SettingsFragment extends PreferenceFragmentCompat { public class SettingsFragment extends PreferenceFragmentCompat {
public static final String KEY_UDP_BROADCAST_ENABLED = "udp_broadcast_enabled";
public static final String KEY_APP_THEME = "theme_pref"; public static final String KEY_APP_THEME = "theme_pref";
private EditTextPreference renameDevice; private EditTextPreference renameDevice;
@@ -171,12 +170,6 @@ public class SettingsFragment extends PreferenceFragmentCompat {
return true; return true;
}); });
// UDP broadcast toggle
final TwoStatePreference udpBroadcastDiscovery = new SwitchPreference(context);
udpBroadcastDiscovery.setDefaultValue(true);
udpBroadcastDiscovery.setKey(KEY_UDP_BROADCAST_ENABLED);
udpBroadcastDiscovery.setTitle(R.string.enable_udp_broadcast);
screen.addPreference(udpBroadcastDiscovery);
// More settings text // More settings text
Preference moreSettingsText = new Preference(context); Preference moreSettingsText = new Preference(context);