Bug 1296464 - [FlyWeb] Machines with multiple interfaces cause duplicate advertisements on all interfaces;r=djvj

This commit is contained in:
jdarcangelo 2016-09-23 19:53:11 -04:00
parent 76b800594e
commit 3cc749444b

View File

@ -100,12 +100,12 @@ class PublishedService {
class MulticastDNS {
constructor() {
this._listeners = new Map();
this._querySocket = undefined;
this._broadcastSocket = undefined;
this._broadcastTimer = undefined;
this._sockets = new Map();
this._services = new Map();
this._discovered = new Map();
this._querySocket = undefined;
this._broadcastReceiverSocket = undefined;
this._broadcastTimer = undefined;
}
startDiscovery(aServiceType, aListener) {
@ -144,6 +144,11 @@ class MulticastDNS {
registerService(aServiceInfo, aListener) {
DEBUG && debug('registerService(): ' + aServiceInfo.serviceName);
// Initialize the broadcast receiver socket in case it
// hasn't already been started so we can listen for
// multicast queries/announcements on all interfaces.
this._getBroadcastReceiverSocket();
for (let name of ['port', 'serviceName', 'serviceType']) {
if (!TryGet(aServiceInfo, name)) {
aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE);
@ -352,7 +357,12 @@ class MulticastDNS {
let data = packet.serialize();
this._getQuerySocket().then(querySocket => {
// Initialize the broadcast receiver socket in case it
// hasn't already been started so we can listen for
// multicast queries/announcements on all interfaces.
this._getBroadcastReceiverSocket();
this._getQuerySocket().then((querySocket) => {
DEBUG && debug('sending query on query socket ("' + name + '")');
querySocket.send(MDNS_MULTICAST_GROUP, MDNS_PORT, data, data.length);
});
@ -559,18 +569,55 @@ class MulticastDNS {
DEBUG && debug('_onServiceFound()' + serviceInfo.serviceName);
}
/**
* Gets a non-exclusive socket on 0.0.0.0:{random} to send
* multicast queries on all interfaces. This socket does
* not need to join a multicast group since it is still
* able to *send* multicast queries, but it does not need
* to *listen* for multicast queries/announcements since
* the `_broadcastReceiverSocket` is already handling them.
*/
_getQuerySocket() {
return new Promise((resolve, reject) => {
if (!this._querySocket) {
this._querySocket = _openSocket(0, {
onPacketReceived: this._onResponsePacketReceived.bind(this),
onStopListening: this._onResponseStopListening.bind(this)
}, /* joinMulticast = */ false);
this._querySocket = _openSocket('0.0.0.0', 0, {
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this)
});
}
resolve(this._querySocket);
});
}
/**
* Gets a non-exclusive socket on 0.0.0.0:5353 to listen
* for multicast queries/announcements on all interfaces.
* Since this socket needs to listen for multicast queries
* and announcements, this socket joins the multicast
* group on *all* interfaces (0.0.0.0).
*/
_getBroadcastReceiverSocket() {
return new Promise((resolve, reject) => {
if (!this._broadcastReceiverSocket) {
this._broadcastReceiverSocket = _openSocket('0.0.0.0', MDNS_PORT, {
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this)
}, /* multicastInterface = */ '0.0.0.0');
}
resolve(this._broadcastReceiverSocket);
});
}
/**
* Gets a non-exclusive socket for each interface on
* {iface-ip}:5353 for sending query responses as
* well as for listening for unicast queries. These
* sockets do not need to join a multicast group
* since they are still able to *send* multicast
* query responses, but they do not need to *listen*
* for multicast queries since the `_querySocket` is
* already handling them.
*/
_getSockets() {
return new Promise((resolve) => {
if (this._sockets.size > 0) {
@ -580,10 +627,7 @@ class MulticastDNS {
Promise.all([getAddresses(), getHostname()]).then(() => {
_addresses.forEach((address) => {
let socket = _openSocket(MDNS_PORT, {
onPacketReceived: this._onPacketReceived.bind(this),
onStopListening: this._onStopListening.bind(this)
}, /* joinMulticast = */ address);
let socket = _openSocket(address, MDNS_PORT, null);
this._sockets.set(address, socket);
});
@ -592,16 +636,6 @@ class MulticastDNS {
});
}
_getBroadcastSocket() {
return new Promise((resolve) => {
if (!this._broadcastSocket) {
this._broadcastSocket = _openSocket(MDNS_PORT, null,
/* joinMulticast = */ false);
}
resolve(this._broadcastSocket);
});
}
_checkCloseSockets() {
// Nothing to do if no sockets to close.
if (this._sockets.size == 0)
@ -624,11 +658,6 @@ class MulticastDNS {
this._sockets.clear();
}
_onResponsePacketReceived(socket, message) {
DEBUG && debug('_onResponsePacketReceived');
this._onPacketReceived(socket, message);
}
_onPacketReceived(socket, message) {
let packet = DNSPacket.parse(message.rawData);
@ -648,11 +677,6 @@ class MulticastDNS {
DEBUG && debug('_onStopListening() ' + status);
}
_onResponseStopListening(socket, status) {
DEBUG && debug('_onResponseStopListening() ' + status);
}
_addServiceListener(serviceType, listener) {
let listeners = this._listeners.get(serviceType);
if (!listeners) {
@ -682,8 +706,8 @@ class MulticastDNS {
}
}
let _networkInfo = Cc['@mozilla.org/network-info-service;1']
.createInstance(Ci.nsINetworkInfoService);
let networkInfoService = Cc['@mozilla.org/network-info-service;1']
.createInstance(Ci.nsINetworkInfoService);
let _addresses;
@ -697,7 +721,7 @@ function getAddresses() {
return;
}
_networkInfo.listNetworkAddresses({
networkInfoService.listNetworkAddresses({
onListedNetworkAddresses(aAddressArray) {
_addresses = aAddressArray.filter((address) => {
return address.indexOf('%p2p') === -1 && // No WiFi Direct interfaces
@ -729,7 +753,7 @@ function getHostname() {
return;
}
_networkInfo.getHostname({
networkInfoService.getHostname({
onGotHostname(aHostname) {
_hostname = aHostname.replace(/\s/g, '-') + '.local';
@ -791,22 +815,20 @@ function _propertyBagToObject(propBag) {
/**
* @private
*/
function _openSocket(port, handler, joinMulticast) {
let socket = Cc['@mozilla.org/network/udp-socket;1']
.createInstance(Ci.nsIUDPSocket);
function _openSocket(addr, port, handler, multicastInterface) {
let socket = Cc['@mozilla.org/network/udp-socket;1'].createInstance(Ci.nsIUDPSocket);
socket.init2(addr, port, Services.scriptSecurityManager.getSystemPrincipal(), true);
if (arguments.length <= 2)
joinMulticast = true;
socket.init(port, false,
Services.scriptSecurityManager.getSystemPrincipal());
if (handler) {
socket.asyncListen({
onPacketReceived: handler.onPacketReceived,
onStopListening: handler.onStopListening
});
}
if (joinMulticast !== false)
socket.joinMulticast(MDNS_MULTICAST_GROUP, joinMulticast);
if (multicastInterface) {
socket.joinMulticast(MDNS_MULTICAST_GROUP, multicastInterface);
}
return socket;
}