summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm')
-rw-r--r--netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm262
1 files changed, 262 insertions, 0 deletions
diff --git a/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
new file mode 100644
index 0000000000..d94e90efaa
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
@@ -0,0 +1,262 @@
+// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["MulticastDNS"];
+
+const { EventDispatcher } = ChromeUtils.import(
+ "resource://gre/modules/Messaging.jsm"
+);
+
+const DEBUG = false;
+
+var log = function(s) {};
+if (DEBUG) {
+ log = ChromeUtils.import(
+ "resource://gre/modules/AndroidLog.jsm",
+ {}
+ ).AndroidLog.d.bind(null, "MulticastDNS");
+}
+
+const FAILURE_INTERNAL_ERROR = -65537;
+
+// Helper function for sending commands to Java.
+function send(type, data, callback) {
+ let msg = {
+ type,
+ };
+
+ for (let i in data) {
+ try {
+ msg[i] = data[i];
+ } catch (e) {}
+ }
+
+ EventDispatcher.instance.sendRequestForResult(msg).then(
+ result => callback(result, null),
+ err =>
+ callback(null, typeof err === "number" ? err : FAILURE_INTERNAL_ERROR)
+ );
+}
+
+// Receives service found/lost event from NsdManager
+function ServiceManager() {}
+
+ServiceManager.prototype = {
+ listeners: {},
+ numListeners: 0,
+
+ onEvent(event, data, callback) {
+ if (event === "NsdManager:ServiceFound") {
+ this.onServiceFound();
+ } else if (event === "NsdManager:ServiceLost") {
+ this.onServiceLost();
+ }
+ },
+
+ registerEvent() {
+ log("registerEvent");
+ EventDispatcher.instance.registerListener(this, [
+ "NsdManager:ServiceFound",
+ "NsdManager:ServiceLost",
+ ]);
+ },
+
+ unregisterEvent() {
+ log("unregisterEvent");
+ EventDispatcher.instance.unregisterListener(this, [
+ "NsdManager:ServiceFound",
+ "NsdManager:ServiceLost",
+ ]);
+ },
+
+ addListener(aServiceType, aListener) {
+ log("addListener: " + aServiceType + ", " + aListener);
+
+ if (!this.listeners[aServiceType]) {
+ this.listeners[aServiceType] = [];
+ }
+ if (this.listeners[aServiceType].includes(aListener)) {
+ log("listener already exists");
+ return;
+ }
+
+ this.listeners[aServiceType].push(aListener);
+ ++this.numListeners;
+
+ if (this.numListeners === 1) {
+ this.registerEvent();
+ }
+
+ log("listener added: " + this);
+ },
+
+ removeListener(aServiceType, aListener) {
+ log("removeListener: " + aServiceType + ", " + aListener);
+
+ if (!this.listeners[aServiceType]) {
+ log("listener doesn't exist");
+ return;
+ }
+ let index = this.listeners[aServiceType].indexOf(aListener);
+ if (index < 0) {
+ log("listener doesn't exist");
+ return;
+ }
+
+ this.listeners[aServiceType].splice(index, 1);
+ --this.numListeners;
+
+ if (this.numListeners === 0) {
+ this.unregisterEvent();
+ }
+
+ log("listener removed" + this);
+ },
+
+ onServiceFound(aServiceInfo) {
+ let listeners = this.listeners[aServiceInfo.serviceType];
+ if (listeners) {
+ for (let listener of listeners) {
+ listener.onServiceFound(aServiceInfo);
+ }
+ } else {
+ log("no listener");
+ }
+ return {};
+ },
+
+ onServiceLost(aServiceInfo) {
+ let listeners = this.listeners[aServiceInfo.serviceType];
+ if (listeners) {
+ for (let listener of listeners) {
+ listener.onServiceLost(aServiceInfo);
+ }
+ } else {
+ log("no listener");
+ }
+ return {};
+ },
+};
+
+// make an object from nsIPropertyBag2
+function parsePropertyBag2(bag) {
+ if (!bag || !(bag instanceof Ci.nsIPropertyBag2)) {
+ throw new TypeError("Not a property bag");
+ }
+
+ let attributes = [];
+ for (let { name } of bag.enumerator) {
+ let value = bag.getPropertyAsACString(name);
+ attributes.push({
+ name,
+ value,
+ });
+ }
+
+ return attributes;
+}
+
+function MulticastDNS() {
+ this.serviceManager = new ServiceManager();
+}
+
+MulticastDNS.prototype = {
+ startDiscovery(aServiceType, aListener) {
+ this.serviceManager.addListener(aServiceType, aListener);
+
+ let serviceInfo = {
+ serviceType: aServiceType,
+ uniqueId: aListener.uuid,
+ };
+
+ send("NsdManager:DiscoverServices", serviceInfo, (result, err) => {
+ if (err) {
+ log("onStartDiscoveryFailed: " + aServiceType + " (" + err + ")");
+ this.serviceManager.removeListener(aServiceType, aListener);
+ aListener.onStartDiscoveryFailed(aServiceType, err);
+ } else {
+ aListener.onDiscoveryStarted(result);
+ }
+ });
+ },
+
+ stopDiscovery(aServiceType, aListener) {
+ this.serviceManager.removeListener(aServiceType, aListener);
+
+ let serviceInfo = {
+ uniqueId: aListener.uuid,
+ };
+
+ send("NsdManager:StopServiceDiscovery", serviceInfo, (result, err) => {
+ if (err) {
+ log("onStopDiscoveryFailed: " + aServiceType + " (" + err + ")");
+ aListener.onStopDiscoveryFailed(aServiceType, err);
+ } else {
+ aListener.onDiscoveryStopped(aServiceType);
+ }
+ });
+ },
+
+ registerService(aServiceInfo, aListener) {
+ let serviceInfo = {
+ port: aServiceInfo.port,
+ serviceType: aServiceInfo.serviceType,
+ uniqueId: aListener.uuid,
+ };
+
+ try {
+ serviceInfo.host = aServiceInfo.host;
+ } catch (e) {
+ // host unspecified
+ }
+ try {
+ serviceInfo.serviceName = aServiceInfo.serviceName;
+ } catch (e) {
+ // serviceName unspecified
+ }
+ try {
+ serviceInfo.attributes = parsePropertyBag2(aServiceInfo.attributes);
+ } catch (e) {
+ // attributes unspecified
+ }
+
+ send("NsdManager:RegisterService", serviceInfo, (result, err) => {
+ if (err) {
+ log("onRegistrationFailed: (" + err + ")");
+ aListener.onRegistrationFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceRegistered(result);
+ }
+ });
+ },
+
+ unregisterService(aServiceInfo, aListener) {
+ let serviceInfo = {
+ uniqueId: aListener.uuid,
+ };
+
+ send("NsdManager:UnregisterService", serviceInfo, (result, err) => {
+ if (err) {
+ log("onUnregistrationFailed: (" + err + ")");
+ aListener.onUnregistrationFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceUnregistered(aServiceInfo);
+ }
+ });
+ },
+
+ resolveService(aServiceInfo, aListener) {
+ send("NsdManager:ResolveService", aServiceInfo, (result, err) => {
+ if (err) {
+ log("onResolveFailed: (" + err + ")");
+ aListener.onResolveFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceResolved(result);
+ }
+ });
+ },
+};