diff options
Diffstat (limited to 'netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm')
-rw-r--r-- | netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm b/netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm new file mode 100644 index 0000000000..bf153ea1bd --- /dev/null +++ b/netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm @@ -0,0 +1,219 @@ +/* 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"; + +const { AppConstants } = ChromeUtils.import( + "resource://gre/modules/AppConstants.jsm" +); +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +const { MulticastDNS } = ChromeUtils.import( + AppConstants.platform == "android" && + !Services.prefs.getBoolPref("network.mdns.use_js_fallback") + ? "resource://gre/modules/MulticastDNSAndroid.jsm" + : "resource://gre/modules/MulticastDNS.jsm" +); + +const DNSSERVICEINFO_CONTRACT_ID = + "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1"; + +function log(aMsg) { + dump("-*- nsDNSServiceDiscovery.js : " + aMsg + "\n"); +} + +function generateUuid() { + var uuidGenerator = Cc["@mozilla.org/uuid-generator;1"].getService( + Ci.nsIUUIDGenerator + ); + return uuidGenerator.generateUUID().toString(); +} + +// Helper class to transform return objects to correct type. +function ListenerWrapper(aListener, aMdns) { + this.listener = aListener; + this.mdns = aMdns; + + this.discoveryStarting = false; + this.stopDiscovery = false; + + this.registrationStarting = false; + this.stopRegistration = false; + + this.uuid = generateUuid(); +} + +ListenerWrapper.prototype = { + // Helper function for transforming an Object into nsIDNSServiceInfo. + makeServiceInfo(aServiceInfo) { + let serviceInfo = Cc[DNSSERVICEINFO_CONTRACT_ID].createInstance( + Ci.nsIDNSServiceInfo + ); + + for (let name of [ + "host", + "address", + "port", + "serviceName", + "serviceType", + ]) { + try { + serviceInfo[name] = aServiceInfo[name]; + } catch (e) { + // ignore exceptions + } + } + + let attributes; + try { + attributes = _toPropertyBag2(aServiceInfo.attributes); + } catch (err) { + // Ignore unset attributes in object. + log("Caught unset attributes error: " + err + " - " + err.stack); + attributes = Cc["@mozilla.org/hash-property-bag;1"].createInstance( + Ci.nsIWritablePropertyBag2 + ); + } + serviceInfo.attributes = attributes; + + return serviceInfo; + }, + + /* transparent types */ + onDiscoveryStarted(aServiceType) { + this.discoveryStarting = false; + this.listener.onDiscoveryStarted(aServiceType); + + if (this.stopDiscovery) { + this.mdns.stopDiscovery(aServiceType, this); + } + }, + onDiscoveryStopped(aServiceType) { + this.listener.onDiscoveryStopped(aServiceType); + }, + onStartDiscoveryFailed(aServiceType, aErrorCode) { + log("onStartDiscoveryFailed: " + aServiceType + " (" + aErrorCode + ")"); + this.discoveryStarting = false; + this.stopDiscovery = true; + this.listener.onStartDiscoveryFailed(aServiceType, aErrorCode); + }, + onStopDiscoveryFailed(aServiceType, aErrorCode) { + log("onStopDiscoveryFailed: " + aServiceType + " (" + aErrorCode + ")"); + this.listener.onStopDiscoveryFailed(aServiceType, aErrorCode); + }, + + /* transform types */ + onServiceFound(aServiceInfo) { + this.listener.onServiceFound(this.makeServiceInfo(aServiceInfo)); + }, + onServiceLost(aServiceInfo) { + this.listener.onServiceLost(this.makeServiceInfo(aServiceInfo)); + }, + onServiceRegistered(aServiceInfo) { + this.registrationStarting = false; + this.listener.onServiceRegistered(this.makeServiceInfo(aServiceInfo)); + + if (this.stopRegistration) { + this.mdns.unregisterService(aServiceInfo, this); + } + }, + onServiceUnregistered(aServiceInfo) { + this.listener.onServiceUnregistered(this.makeServiceInfo(aServiceInfo)); + }, + onServiceResolved(aServiceInfo) { + this.listener.onServiceResolved(this.makeServiceInfo(aServiceInfo)); + }, + + onRegistrationFailed(aServiceInfo, aErrorCode) { + log("onRegistrationFailed: (" + aErrorCode + ")"); + this.registrationStarting = false; + this.stopRegistration = true; + this.listener.onRegistrationFailed( + this.makeServiceInfo(aServiceInfo), + aErrorCode + ); + }, + onUnregistrationFailed(aServiceInfo, aErrorCode) { + log("onUnregistrationFailed: (" + aErrorCode + ")"); + this.listener.onUnregistrationFailed( + this.makeServiceInfo(aServiceInfo), + aErrorCode + ); + }, + onResolveFailed(aServiceInfo, aErrorCode) { + log("onResolveFailed: (" + aErrorCode + ")"); + this.listener.onResolveFailed( + this.makeServiceInfo(aServiceInfo), + aErrorCode + ); + }, +}; + +function nsDNSServiceDiscovery() { + log("nsDNSServiceDiscovery"); + this.mdns = new MulticastDNS(); +} + +nsDNSServiceDiscovery.prototype = { + QueryInterface: ChromeUtils.generateQI([ + "nsISupportsWeakReference", + "nsIDNSServiceDiscovery", + ]), + + startDiscovery(aServiceType, aListener) { + log("startDiscovery"); + let listener = new ListenerWrapper(aListener, this.mdns); + listener.discoveryStarting = true; + this.mdns.startDiscovery(aServiceType, listener); + + return { + QueryInterface: ChromeUtils.generateQI(["nsICancelable"]), + cancel: function() { + if (this.discoveryStarting || this.stopDiscovery) { + this.stopDiscovery = true; + return; + } + this.mdns.stopDiscovery(aServiceType, listener); + }.bind(listener), + }; + }, + + registerService(aServiceInfo, aListener) { + log("registerService"); + let listener = new ListenerWrapper(aListener, this.mdns); + listener.registrationStarting = true; + this.mdns.registerService(aServiceInfo, listener); + + return { + QueryInterface: ChromeUtils.generateQI(["nsICancelable"]), + cancel: function() { + if (this.registrationStarting || this.stopRegistration) { + this.stopRegistration = true; + return; + } + this.mdns.unregisterService(aServiceInfo, listener); + }.bind(listener), + }; + }, + + resolveService(aServiceInfo, aListener) { + log("resolveService"); + this.mdns.resolveService(aServiceInfo, new ListenerWrapper(aListener)); + }, +}; + +var EXPORTED_SYMBOLS = ["nsDNSServiceDiscovery"]; + +function _toPropertyBag2(obj) { + if (obj.QueryInterface) { + return obj.QueryInterface(Ci.nsIPropertyBag2); + } + + let result = Cc["@mozilla.org/hash-property-bag;1"].createInstance( + Ci.nsIWritablePropertyBag2 + ); + for (let name in obj) { + result.setPropertyAsAString(name, obj[name]); + } + return result; +} |