Bug 1193605 - Part 5: separate different discovery/registration requests by UUIDs; r=rnewman

This commit is contained in:
Liang-Heng Chen 2015-09-09 08:30:00 +02:00
parent 3e97970d14
commit 4225be33fd
2 changed files with 130 additions and 80 deletions

View File

@ -27,6 +27,7 @@ import android.util.Log;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* This class is the bridge between XPCOM mDNS module and NsdManager. * This class is the bridge between XPCOM mDNS module and NsdManager.
@ -110,13 +111,15 @@ class MulticastDNSEventManager {
class NsdMulticastDNSManager extends MulticastDNSManager implements NativeEventListener { class NsdMulticastDNSManager extends MulticastDNSManager implements NativeEventListener {
private final NsdManager nsdManager; private final NsdManager nsdManager;
private final MulticastDNSEventManager mEventManager; private final MulticastDNSEventManager mEventManager;
private DiscoveryListener mDiscoveryListener = null; private Map<String, DiscoveryListener> mDiscoveryListeners = null;
private RegistrationListener mRegistrationListener = null; private Map<String, RegistrationListener> mRegistrationListeners = null;
@TargetApi(16) @TargetApi(16)
public NsdMulticastDNSManager(final Context context) { public NsdMulticastDNSManager(final Context context) {
nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE); nsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
mEventManager = new MulticastDNSEventManager(this); mEventManager = new MulticastDNSEventManager(this);
mDiscoveryListeners = new ConcurrentHashMap<String, DiscoveryListener>();
mRegistrationListeners = new ConcurrentHashMap<String, RegistrationListener>();
} }
@Override @Override
@ -126,6 +129,9 @@ class NsdMulticastDNSManager extends MulticastDNSManager implements NativeEventL
@Override @Override
public void tearDown() { public void tearDown() {
mDiscoveryListeners.clear();
mRegistrationListeners.clear();
mEventManager.tearDown(); mEventManager.tearDown();
} }
@ -134,42 +140,49 @@ class NsdMulticastDNSManager extends MulticastDNSManager implements NativeEventL
Log.v(LOGTAG, "handleMessage: " + event); Log.v(LOGTAG, "handleMessage: " + event);
switch (event) { switch (event) {
case "NsdManager:DiscoverServices": case "NsdManager:DiscoverServices": {
if (mDiscoveryListener != null) { DiscoveryListener listener = new DiscoveryListener(nsdManager);
mDiscoveryListener.stopServiceDiscovery(null); listener.discoverServices(message.getString("serviceType"), callback);
} mDiscoveryListeners.put(message.getString("uniqueId"), listener);
mDiscoveryListener = new DiscoveryListener(nsdManager);
mDiscoveryListener.discoverServices(message.getString("serviceType"), callback);
break; break;
case "NsdManager:StopServiceDiscovery": }
if (mDiscoveryListener != null) { case "NsdManager:StopServiceDiscovery": {
mDiscoveryListener.stopServiceDiscovery(callback); String uuid = message.getString("uniqueId");
mDiscoveryListener = null; DiscoveryListener listener = mDiscoveryListeners.remove(uuid);
if (listener == null) {
Log.e(LOGTAG, "DiscoveryListener " + uuid + " was not found.");
return;
} }
listener.stopServiceDiscovery(callback);
break; break;
case "NsdManager:RegisterService": }
if (mRegistrationListener != null) { case "NsdManager:RegisterService": {
mRegistrationListener.unregisterService(null); RegistrationListener listener = new RegistrationListener(nsdManager);
} listener.registerService(message.getInt("port"),
mRegistrationListener = new RegistrationListener(nsdManager);
mRegistrationListener.registerService(message.getInt("port"),
message.optString("serviceName", android.os.Build.MODEL), message.optString("serviceName", android.os.Build.MODEL),
message.getString("serviceType"), message.getString("serviceType"),
parseAttributes(message.optObjectArray("attributes", null)), parseAttributes(message.optObjectArray("attributes", null)),
callback); callback);
mRegistrationListeners.put(message.getString("uniqueId"), listener);
break; break;
case "NsdManager:UnregisterService": }
if (mRegistrationListener != null) { case "NsdManager:UnregisterService": {
mRegistrationListener.unregisterService(callback); String uuid = message.getString("uniqueId");
mRegistrationListener = null; RegistrationListener listener = mRegistrationListeners.remove(uuid);
if (listener == null) {
Log.e(LOGTAG, "RegistrationListener " + uuid + " was not found.");
return;
} }
listener.unregisterService(callback);
break; break;
case "NsdManager:ResolveService": }
case "NsdManager:ResolveService": {
(new ResolveListener(nsdManager)).resolveService(message.getString("serviceName"), (new ResolveListener(nsdManager)).resolveService(message.getString("serviceName"),
message.getString("serviceType"), message.getString("serviceType"),
callback); callback);
break; break;
}; }
}
} }
private Map<String, String> parseAttributes(final NativeJSObject[] jsobjs) { private Map<String, String> parseAttributes(final NativeJSObject[] jsobjs) {
@ -253,9 +266,6 @@ class DiscoveryListener implements NsdManager.DiscoveryListener {
public void discoverServices(final String serviceType, final EventCallback callback) { public void discoverServices(final String serviceType, final EventCallback callback) {
synchronized (this) { synchronized (this) {
if (mStartCallback != null) {
throw new RuntimeException("Previous operation is not finished");
}
mStartCallback = callback; mStartCallback = callback;
} }
nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, this); nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, this);
@ -263,9 +273,6 @@ class DiscoveryListener implements NsdManager.DiscoveryListener {
public void stopServiceDiscovery(final EventCallback callback) { public void stopServiceDiscovery(final EventCallback callback) {
synchronized (this) { synchronized (this) {
if (mStopCallback != null) {
throw new RuntimeException("Previous operation is not finished");
}
mStopCallback = callback; mStopCallback = callback;
} }
nsdManager.stopServiceDiscovery(this); nsdManager.stopServiceDiscovery(this);
@ -274,47 +281,67 @@ class DiscoveryListener implements NsdManager.DiscoveryListener {
@Override @Override
public synchronized void onDiscoveryStarted(final String serviceType) { public synchronized void onDiscoveryStarted(final String serviceType) {
Log.d(LOGTAG, "onDiscoveryStarted: " + serviceType); Log.d(LOGTAG, "onDiscoveryStarted: " + serviceType);
if (mStartCallback == null) {
EventCallback callback;
synchronized (this) {
callback = mStartCallback;
}
if (callback == null) {
return; return;
} }
mStartCallback.sendSuccess(serviceType);
mStartCallback = null; callback.sendSuccess(serviceType);
} }
@Override @Override
public synchronized void onStartDiscoveryFailed(final String serviceType, final int errorCode) { public synchronized void onStartDiscoveryFailed(final String serviceType, final int errorCode) {
Log.e(LOGTAG, "onStartDiscoveryFailed: " + serviceType + "(" + errorCode + ")"); Log.e(LOGTAG, "onStartDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
if (mStartCallback == null) {
return; EventCallback callback;
synchronized (this) {
callback = mStartCallback;
} }
mStartCallback.sendError(errorCode);
mStartCallback = null; callback.sendError(errorCode);
} }
@Override @Override
public synchronized void onDiscoveryStopped(final String serviceType) { public synchronized void onDiscoveryStopped(final String serviceType) {
Log.d(LOGTAG, "onDiscoveryStopped: " + serviceType); Log.d(LOGTAG, "onDiscoveryStopped: " + serviceType);
if (mStopCallback == null) {
EventCallback callback;
synchronized (this) {
callback = mStopCallback;
}
if (callback == null) {
return; return;
} }
mStopCallback.sendSuccess(serviceType);
mStopCallback = null; callback.sendSuccess(serviceType);
} }
@Override @Override
public synchronized void onStopDiscoveryFailed(final String serviceType, final int errorCode) { public synchronized void onStopDiscoveryFailed(final String serviceType, final int errorCode) {
Log.e(LOGTAG, "onStopDiscoveryFailed: " + serviceType + "(" + errorCode + ")"); Log.e(LOGTAG, "onStopDiscoveryFailed: " + serviceType + "(" + errorCode + ")");
if (mStopCallback == null) {
EventCallback callback;
synchronized (this) {
callback = mStopCallback;
}
if (callback == null) {
return; return;
} }
mStopCallback.sendError(errorCode);
mStopCallback = null; callback.sendError(errorCode);
} }
@Override @Override
public void onServiceFound(final NsdServiceInfo serviceInfo) { public void onServiceFound(final NsdServiceInfo serviceInfo) {
Log.d(LOGTAG, "onServiceFound: " + serviceInfo.getServiceName()); Log.d(LOGTAG, "onServiceFound: " + serviceInfo.getServiceName());
JSONObject json = null; JSONObject json;
try { try {
json = NsdMulticastDNSManager.toJSON(serviceInfo); json = NsdMulticastDNSManager.toJSON(serviceInfo);
} catch (JSONException e) { } catch (JSONException e) {
@ -331,7 +358,7 @@ class DiscoveryListener implements NsdManager.DiscoveryListener {
@Override @Override
public void onServiceLost(final NsdServiceInfo serviceInfo) { public void onServiceLost(final NsdServiceInfo serviceInfo) {
Log.d(LOGTAG, "onServiceLost: " + serviceInfo.getServiceName()); Log.d(LOGTAG, "onServiceLost: " + serviceInfo.getServiceName());
JSONObject json = null; JSONObject json;
try { try {
json = NsdMulticastDNSManager.toJSON(serviceInfo); json = NsdMulticastDNSManager.toJSON(serviceInfo);
} catch (JSONException e) { } catch (JSONException e) {
@ -361,18 +388,16 @@ class RegistrationListener implements NsdManager.RegistrationListener {
public void registerService(final int port, final String serviceName, final String serviceType, final Map<String, String> attributes, final EventCallback callback) { public void registerService(final int port, final String serviceName, final String serviceType, final Map<String, String> attributes, final EventCallback callback) {
Log.d(LOGTAG, "registerService: " + serviceName + "." + serviceType + ":" + port); Log.d(LOGTAG, "registerService: " + serviceName + "." + serviceType + ":" + port);
synchronized (this) {
if (mStartCallback != null) {
throw new RuntimeException("Previous operation is not finished");
}
mStartCallback = callback;
}
NsdServiceInfo serviceInfo = new NsdServiceInfo(); NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setPort(port); serviceInfo.setPort(port);
serviceInfo.setServiceName(serviceName); serviceInfo.setServiceName(serviceName);
serviceInfo.setServiceType(serviceType); serviceInfo.setServiceType(serviceType);
setAttributes(serviceInfo, attributes); setAttributes(serviceInfo, attributes);
synchronized (this) {
mStartCallback = callback;
}
nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this); nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this);
} }
@ -390,11 +415,9 @@ class RegistrationListener implements NsdManager.RegistrationListener {
public void unregisterService(final EventCallback callback) { public void unregisterService(final EventCallback callback) {
Log.d(LOGTAG, "unregisterService"); Log.d(LOGTAG, "unregisterService");
synchronized (this) { synchronized (this) {
if (mStopCallback != null) {
throw new RuntimeException("Previous operation is not finished");
}
mStopCallback = callback; mStopCallback = callback;
} }
nsdManager.unregisterService(this); nsdManager.unregisterService(this);
} }
@ -402,51 +425,68 @@ class RegistrationListener implements NsdManager.RegistrationListener {
public synchronized void onServiceRegistered(final NsdServiceInfo serviceInfo) { public synchronized void onServiceRegistered(final NsdServiceInfo serviceInfo) {
Log.d(LOGTAG, "onServiceRegistered: " + serviceInfo.getServiceName()); Log.d(LOGTAG, "onServiceRegistered: " + serviceInfo.getServiceName());
if (mStartCallback == null) { EventCallback callback;
synchronized (this) {
callback = mStartCallback;
}
if (callback == null) {
return; return;
} }
try { try {
mStartCallback.sendSuccess(NsdMulticastDNSManager.toJSON(serviceInfo)); callback.sendSuccess(NsdMulticastDNSManager.toJSON(serviceInfo));
} catch (JSONException e) { } catch (JSONException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
mStartCallback = null;
} }
@Override @Override
public synchronized void onRegistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) { public synchronized void onRegistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
Log.e(LOGTAG, "onRegistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")"); Log.e(LOGTAG, "onRegistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
if (mStartCallback == null) {
return; EventCallback callback;
synchronized (this) {
callback = mStartCallback;
} }
mStartCallback.sendError(errorCode);
mStartCallback = null; callback.sendError(errorCode);
} }
@Override @Override
public synchronized void onServiceUnregistered(final NsdServiceInfo serviceInfo) { public synchronized void onServiceUnregistered(final NsdServiceInfo serviceInfo) {
Log.d(LOGTAG, "onServiceUnregistered: " + serviceInfo.getServiceName()); Log.d(LOGTAG, "onServiceUnregistered: " + serviceInfo.getServiceName());
if (mStopCallback == null) {
EventCallback callback;
synchronized (this) {
callback = mStopCallback;
}
if (callback == null) {
return; return;
} }
try { try {
mStopCallback.sendSuccess(NsdMulticastDNSManager.toJSON(serviceInfo)); callback.sendSuccess(NsdMulticastDNSManager.toJSON(serviceInfo));
} catch (JSONException e) { } catch (JSONException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
mStopCallback = null;
} }
@Override @Override
public synchronized void onUnregistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) { public synchronized void onUnregistrationFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
Log.e(LOGTAG, "onUnregistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")"); Log.e(LOGTAG, "onUnregistrationFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
if (mStopCallback == null) {
EventCallback callback;
synchronized (this) {
callback = mStopCallback;
}
if (callback == null) {
return; return;
} }
mStopCallback.sendError(errorCode);
mStopCallback = null; callback.sendError(errorCode);
} }
} }
@ -463,16 +503,11 @@ class ResolveListener implements NsdManager.ResolveListener {
} }
public void resolveService(final String serviceName, final String serviceType, final EventCallback callback) { public void resolveService(final String serviceName, final String serviceType, final EventCallback callback) {
synchronized (this) {
if (mCallback != null) {
throw new RuntimeException("Previous operation is not finished");
}
mCallback = callback;
}
NsdServiceInfo serviceInfo = new NsdServiceInfo(); NsdServiceInfo serviceInfo = new NsdServiceInfo();
serviceInfo.setServiceName(serviceName); serviceInfo.setServiceName(serviceName);
serviceInfo.setServiceType(serviceType); serviceInfo.setServiceType(serviceType);
mCallback = callback;
nsdManager.resolveService(serviceInfo, this); nsdManager.resolveService(serviceInfo, this);
} }
@ -480,16 +515,17 @@ class ResolveListener implements NsdManager.ResolveListener {
@Override @Override
public synchronized void onResolveFailed(final NsdServiceInfo serviceInfo, final int errorCode) { public synchronized void onResolveFailed(final NsdServiceInfo serviceInfo, final int errorCode) {
Log.e(LOGTAG, "onResolveFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")"); Log.e(LOGTAG, "onResolveFailed: " + serviceInfo.getServiceName() + "(" + errorCode + ")");
if (mCallback == null) { if (mCallback == null) {
return; return;
} }
mCallback.sendError(errorCode); mCallback.sendError(errorCode);
mCallback = null;
} }
@Override @Override
public synchronized void onServiceResolved(final NsdServiceInfo serviceInfo) { public synchronized void onServiceResolved(final NsdServiceInfo serviceInfo) {
Log.d(LOGTAG, "onServiceResolved: " + serviceInfo.getServiceName()); Log.d(LOGTAG, "onServiceResolved: " + serviceInfo.getServiceName());
if (mCallback == null) { if (mCallback == null) {
return; return;
} }
@ -499,6 +535,5 @@ class ResolveListener implements NsdManager.ResolveListener {
} catch (JSONException e) { } catch (JSONException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
mCallback = null;
} }
} }

View File

@ -83,6 +83,7 @@ ServiceManager.prototype = {
} }
let index = this.listeners[aServiceType].indexOf(aListener); let index = this.listeners[aServiceType].indexOf(aListener);
if (index < 0) { if (index < 0) {
log("listener doesn't exist");
return; return;
} }
@ -149,7 +150,12 @@ MulticastDNS.prototype = {
startDiscovery: function(aServiceType, aListener) { startDiscovery: function(aServiceType, aListener) {
this.serviceManager.addListener(aServiceType, aListener); this.serviceManager.addListener(aServiceType, aListener);
send("NsdManager:DiscoverServices", { serviceType: aServiceType }, (result, err) => { let serviceInfo = {
serviceType: aServiceType,
uniqueId: aListener.uuid
};
send("NsdManager:DiscoverServices", serviceInfo, (result, err) => {
if (err) { if (err) {
log("onStartDiscoveryFailed: " + aServiceType + " (" + err + ")"); log("onStartDiscoveryFailed: " + aServiceType + " (" + err + ")");
this.serviceManager.removeListener(aServiceType, aListener); this.serviceManager.removeListener(aServiceType, aListener);
@ -163,7 +169,11 @@ MulticastDNS.prototype = {
stopDiscovery: function(aServiceType, aListener) { stopDiscovery: function(aServiceType, aListener) {
this.serviceManager.removeListener(aServiceType, aListener); this.serviceManager.removeListener(aServiceType, aListener);
send("NsdManager:StopServiceDiscovery", {}, (result, err) => { let serviceInfo = {
uniqueId: aListener.uuid
};
send("NsdManager:StopServiceDiscovery", serviceInfo, (result, err) => {
if (err) { if (err) {
log("onStopDiscoveryFailed: " + aServiceType + " (" + err + ")"); log("onStopDiscoveryFailed: " + aServiceType + " (" + err + ")");
aListener.onStopDiscoveryFailed(aServiceType, err); aListener.onStopDiscoveryFailed(aServiceType, err);
@ -177,6 +187,7 @@ MulticastDNS.prototype = {
let serviceInfo = { let serviceInfo = {
port: aServiceInfo.port, port: aServiceInfo.port,
serviceType: aServiceInfo.serviceType, serviceType: aServiceInfo.serviceType,
uniqueId: aListener.uuid
}; };
try { try {
@ -206,7 +217,11 @@ MulticastDNS.prototype = {
}, },
unregisterService: function(aServiceInfo, aListener) { unregisterService: function(aServiceInfo, aListener) {
send("NsdManager:UnregisterService", {}, (result, err) => { let serviceInfo = {
uniqueId: aListener.uuid
};
send("NsdManager:UnregisterService", serviceInfo, (result, err) => {
if (err) { if (err) {
log("onUnregistrationFailed: (" + err + ")"); log("onUnregistrationFailed: (" + err + ")");
aListener.onUnregistrationFailed(aServiceInfo, err); aListener.onUnregistrationFailed(aServiceInfo, err);