Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get node_mdns up to speed #84

Merged
merged 31 commits into from
May 29, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4561d5a
errno -> process._errno
mrose17 May 17, 2013
7f06595
allow interfaceIndex to be "really big"
mrose17 May 29, 2013
e08bddc
errno for 0.8.x and 0.10.x
mrose17 Jun 13, 2013
6ad60ea
Merge pull request #1 from Wizcorp/errno-fixes
Aug 27, 2013
9f64a9d
Update README.textile
Aug 27, 2013
96d91c5
Release
Aug 27, 2013
c6f886a
Renamed the package to mdns2
Aug 27, 2013
3da4104
Changelog
Aug 27, 2013
749b420
Updated readme to reflect new repo location.
Aug 27, 2013
16bb271
Undid Uint32 patch as it broke a test.
Aug 29, 2013
8c50682
Release
Aug 29, 2013
c5098d9
Final fix for Node 0.8 AND 0.10 compatibility.
Aug 29, 2013
d8446ca
Changelog
Aug 29, 2013
2ff8d02
caches interface names in case the interface has been removed
achingbrain Oct 20, 2013
604ef7a
Merge pull request #3 from achingbrain/master
Oct 22, 2013
37cb299
Release notes and version bump
Oct 22, 2013
1103f01
Merge pull request #4 from ronkorving/release
Oct 22, 2013
916a154
uses unsigned ints internally so value of ifaceIdx matches kDNSServic…
achingbrain Oct 22, 2013
634d352
Merge pull request #5 from achingbrain/master
Oct 28, 2013
760d34c
Release
Oct 28, 2013
945cae7
Merge branch 'master' of github.com:Wizcorp/node_mdns
Oct 28, 2013
c92e53b
add example that shows fow to maintain a list of devices on the net, …
MaZderMind Nov 4, 2013
319785a
fix bad path & inconsistent filename
MaZderMind Nov 5, 2013
c4d6a2a
Merge pull request #6 from MaZderMind/add-device-list-example
Nov 5, 2013
14c7e3c
Include the service with the error, so it can be dealt with in context
Mar 31, 2014
de4e2fd
Merge pull request #10 from bjornstar/feature/moreErrorContext
Mar 31, 2014
aff697d
add changes for 2.1.4
Mar 31, 2014
3b49b9e
Merge pull request #11 from bjornstar/feature/moreErrorContext
Mar 31, 2014
1f7a632
Version bump
Mar 31, 2014
11d47fe
Moved references back from Wizcorp to agnat.
May 29, 2014
95205d6
Release 2.2.0
May 29, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
CHANGES

Version 2.1.4 to 2.2.0

- moved the repository back from Wizcorp/node_mdns to agnat/node_mdns

Version 2.1.3 to 2.1.4

- added service to errors from the resolver (bjornstar)

Version 2.1.2 to 2.1.3

- applied the fix from 2.1.0 to remaining parts of the code base (achingbrain)

Version 2.1.1 to 2.1.2

- fixed an exception that was thrown when a service went down along with its network interface (achingbrain)

Version 2.1.0 to 2.1.1

- fixed the interfaceIndex patch by mrose17 as it was breaking on Node 0.8 (ronkorving)

Version 2.0.0-dev to 2.1.0

- errno was broken in Node v0.10 (mrose17)
- allow interfaceIndex to be "really big" (mrose17)

Version 1.1.0 to 2.0.0-dev

- empty version release (agnat)

Version 1.0.0 to 1.1.0

- better handling of network interfaces
Expand Down
4 changes: 2 additions & 2 deletions README.textile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ h1. mdns -- node.js Service Discovery

|_. Package: | mdns |
|_. Description: | multicast DNS service discovery |
|_. Version: | 2.0.0-dev |
|_. Version: | 2.2.0 |
|_. Installation: | @npm install mdns@ (see below) |
|_. Documentation: | "mdns user guide":http://agnat.github.com/node_mdns/user_guide.html |
|_. License: | "MIT":http://github.com/agnat/node_mdns/blob/master/LICENSE |
Expand Down Expand Up @@ -34,7 +34,7 @@ var all_the_types = mdns.browseThemAll(); // all_the_types is just another brows

h2. Installation

On Linux and other systems using the avahi daemon the avahi dns_sd compat library and its header files are required. On debianesque systems the package name is @libavahi-compat-libdnssd-dev@. On other platforms Apples "mDNSResponder":http://opensource.apple.com/tarballs/mDNSResponder/ is recommended. Care should be taken not to install more than one mDNS stack on a system.
On Linux and other systems using the avahi daemon the avahi dns_sd compat library and its header files are required. On debianesque systems the package name is @libavahi-compat-libdnssd-dev@. On other platforms Apples "mDNSResponder":http://opensource.apple.com/tarballs/mDNSResponder/ is recommended. Care should be taken not to install more than one mDNS stack on a system.

On Windows you are going to need Apples "Bonjour SDK for Windows". You can download it either from Apple (registration required) or various unofficial sources. Take your pick. After installing the SDK restart your shell or command prompt and make sure the @BONJOUR_SDK_HOME@ environment variable is set. You'll also need a compiler. Microsoft Visual Studio Express will do. On Windows node >=0.7.9 is required.

Expand Down
31 changes: 31 additions & 0 deletions examples/osc_devices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env node
var mdns = require('../lib/mdns')
, listOfOscDevices = { /*name: {adresses: ['192.168.0.24', 'fe80::0:18'], port: 10001}}*/ }
;

var mdnsBrowser = mdns.createBrowser(mdns.udp('osc'));

mdnsBrowser.on('serviceUp', function(service) {
// ignore duplicate ups
if(listOfOscDevices[service.name]) return;

listOfOscDevices[service.name] = {'addresses': service.addresses, 'port': service.port};
var cnt = Object.keys(listOfOscDevices).length;

console.log('osc device "'+service.name+' up at '+service.addresses[0]+':'+service.port+', now '+cnt+' devices on the net');
});

mdnsBrowser.on('serviceDown', function(service) {
// ignore duplicate downs
if(!listOfOscDevices[service.name]) return;

var device = listOfOscDevices[service.name];

delete listOfOscDevices[service.name];
var cnt = Object.keys(listOfOscDevices).length;

console.log('osc device "'+service.name+' up at '+device.addresses[0]+':'+device.port+', now '+cnt+' devices on the net');
});

console.log('listening for osc-compatible devices on the net')
mdnsBrowser.start();
2 changes: 1 addition & 1 deletion lib/advertisement.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function Advertisement(serviceType, port, options, callback) {
, domain: domain
, flags: flags
}, context);
}
}
if (error) {
self.emit('error', error);
}
Expand Down
22 changes: 17 additions & 5 deletions lib/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ var Browser = exports.Browser = function Browser(serviceType, options) {
, requested_type = st.makeServiceType( serviceType );
;

var interfaceNames = [];

function on_service_changed(sdRef, flags, ifaceIdx, errorCode, serviceName,
serviceType, replyDomain, context)
{
function on_resolver_done(error, service) {
if (error) {
self.emit('error', error);
self.emit('error', error, service);
} else {
self.emit('serviceChanged', service, context);
self.emit('serviceUp', service, context);
Expand All @@ -42,10 +44,20 @@ var Browser = exports.Browser = function Browser(serviceType, options) {
};
if (serviceName) service.name = serviceName;

if (typeof dns_sd.if_indextoname !== 'undefined' && ifaceIdx > 0) {
service.networkInterface = dns_sd.if_indextoname(ifaceIdx);
} else if (dns_sd.kDNSServiceInterfaceIndexLocalOnly === ifaceIdx) {
if (dns_sd.kDNSServiceInterfaceIndexLocalOnly === ifaceIdx) {
service.networkInterface = nif.loopbackName();
} else if (typeof dns_sd.if_indextoname !== 'undefined' && ifaceIdx > 0) {
try {
service.networkInterface = dns_sd.if_indextoname(ifaceIdx);

interfaceNames[ifaceIdx] = service.networkInterface;
} catch(e) {
if(typeof interfaceNames[ifaceIdx] !== "undefined") {
service.networkInterface = interfaceNames[ifaceIdx];
} else {
throw e;
}
}
}

if (flags & dns_sd.kDNSServiceFlagsAdd) {
Expand Down Expand Up @@ -75,7 +87,7 @@ var resolve = exports.resolve = function resolve(service, sequence, callback) {

function next(error) {
if (error) {
callback(error);
callback(error, service);
return;
}
if (sequence.length === step) {
Expand Down
3 changes: 2 additions & 1 deletion lib/resolver_sequence_tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,10 @@ try {
_getaddrinfo = function getaddrinfo_v06x(host, family, cb) {
var wrap = cares.getaddrinfo(host, family);
if ( ! wrap) {
throw errnoException(errno, 'getaddrinfo');
throw errnoException(process._errno || global.errno, 'getaddrinfo');
}
wrap.oncomplete = function(addresses) {
var errno = process._errno || global.errno;

if (addresses) {
cb(undefined, addresses);
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{ "name": "mdns"
, "version": "2.0.0-dev"
, "version": "2.2.0"
, "description": "multicast DNS service discovery"
, "main": "./lib/mdns.js"
, "scripts":
{ "test": "node utils/testrun"
}
, "keywords": ["zeroconf", "bonjour", "dns_sd", "mDNSResponder"]
, "devDependencies":
, "devDependencies":
{ "ejs": "*"
, "less": "*"
, "mkdirp": "*"
Expand All @@ -15,6 +15,7 @@
, "glob": "*"
, "ncp": "*"
, "minimatch": "*"
, "proxyquire": "~0.5"
}
, "repository":
{ "type": "git"
Expand Down
6 changes: 3 additions & 3 deletions src/dns_service_browse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ OnServiceChanged(DNSServiceRef sdRef, DNSServiceFlags flags,
Local<Value> args[argc];
args[0] = Local<Object>::New(serviceRef->handle_);
args[1] = Integer::New(flags);
args[2] = Integer::New(interfaceIndex);
args[2] = Integer::NewFromUnsigned(interfaceIndex);
args[3] = Integer::New(errorCode);
args[4] = stringOrUndefined(serviceName);
args[5] = stringOrUndefined(serviceType);
Expand Down Expand Up @@ -59,10 +59,10 @@ DNSServiceBrowse(Arguments const& args) {
}
DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

if ( ! args[2]->IsInt32()) {
if ( ! args[2]->IsUint32() && ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
}
uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();
uint32_t interfaceIndex = args[2]->ToInteger()->Uint32Value();

if ( ! args[3]->IsString()) {
return throwTypeError("argument 4 must be a string (service type)");
Expand Down
8 changes: 4 additions & 4 deletions src/dns_service_enumerate_domains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ OnEnumeration(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceInde
Local<Value> args[argc];
args[0] = Local<Object>::New(serviceRef->handle_);
args[1] = Integer::New(flags);
args[2] = Integer::New(interfaceIndex);
args[2] = Integer::NewFromUnsigned(interfaceIndex);
args[3] = Integer::New(errorCode);
args[4] = stringOrUndefined(replyDomain);
args[5] = Local<Value>::New(serviceRef->GetContext());
Expand All @@ -49,10 +49,10 @@ DNSServiceEnumerateDomains(Arguments const& args) {
}
DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

if ( ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
if ( ! args[2]->IsUint32() && ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
}
uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();
uint32_t interfaceIndex = args[2]->ToInteger()->Uint32Value();

if ( ! args[3]->IsFunction()) {
return throwTypeError("argument 4 must be a function (callBack)");
Expand Down
8 changes: 4 additions & 4 deletions src/dns_service_get_addr_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ OnAddressInfo(DNSServiceRef sdRef, DNSServiceFlags flags,
Local<Value> args[argc];
args[0] = Local<Object>::New(serviceRef->handle_);
args[1] = Integer::New(flags);
args[2] = Integer::New(interfaceIndex);
args[2] = Integer::NewFromUnsigned(interfaceIndex);
args[3] = Integer::New(errorCode);
args[4] = stringOrUndefined(hostname);
args[5] = String::Empty();
Expand Down Expand Up @@ -89,10 +89,10 @@ DNSServiceGetAddrInfo(Arguments const& args) {
}
DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

if ( ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
if ( ! args[2]->IsUint32() && ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
}
uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();
uint32_t interfaceIndex = args[2]->ToInteger()->Uint32Value();

if ( ! args[3]->IsInt32()) {
return throwTypeError("argument 4 must be an integer (DNSServiceProtocol)");
Expand Down
6 changes: 3 additions & 3 deletions src/dns_service_register.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ DNSServiceRegister(Arguments const& args) {
if (argumentCountMismatch(args, 11)) {
return throwArgumentCountMismatchException(args, 11);
}

if ( ! ServiceRef::HasInstance(args[0])) {
return throwTypeError("argument 1 must be a DNSServiceRef (sdRef)");
}
Expand All @@ -69,10 +69,10 @@ DNSServiceRegister(Arguments const& args) {
}
DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

if ( ! args[2]->IsInt32()) {
if ( ! args[2]->IsUint32() && ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
}
uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();
uint32_t interfaceIndex = args[2]->ToInteger()->Uint32Value();

bool has_name = false;
if ( ! args[3]->IsNull() && ! args[3]->IsUndefined()) {
Expand Down
6 changes: 3 additions & 3 deletions src/dns_service_resolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ OnResolve(DNSServiceRef sdRef, DNSServiceFlags flags,
Local<Value> args[argc];
args[0] = Local<Object>::New(serviceRef->handle_);
args[1] = Integer::New(flags);
args[2] = Integer::New(interfaceIndex);
args[2] = Integer::NewFromUnsigned(interfaceIndex);
args[3] = Integer::New(errorCode);
args[4] = stringOrUndefined(fullname);
args[5] = stringOrUndefined(hosttarget);
Expand Down Expand Up @@ -72,10 +72,10 @@ DNSServiceResolve(Arguments const& args) {
}
DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

if ( ! args[2]->IsInt32()) {
if ( ! args[2]->IsUint32() && ! args[2]->IsInt32()) {
return throwTypeError("argument 3 must be an integer (interfaceIndex)");
}
uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();
uint32_t interfaceIndex = args[2]->ToInteger()->Uint32Value();

if ( ! args[3]->IsString()) {
return throwTypeError("argument 4 must be a string (name)");
Expand Down
72 changes: 72 additions & 0 deletions tests/test_browser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
var st = require('../lib/service_type.js')
, dns_sd = require('../lib/dns_sd')
, proxyquire = require('proxyquire')
;

//=== Browser ===========================================================

module.exports["Browser"] = {
"Should retrieve interface name from cache when interface index is no longer valid": function(test) {
var callback = null
, invocations = 0
, threwException = false
, interfaceName = "foo"
, serviceName = "_foo._tcp.";

var mock_dns_sd = {
kDNSServiceErr_NoError: dns_sd.kDNSServiceErr_NoError,
kDNSServiceInterfaceIndexLocalOnly: dns_sd.kDNSServiceInterfaceIndexLocalOnly,
kDNSServiceFlagsAdd: dns_sd.kDNSServiceFlagsAdd,

// we stub the if_indextoname method
if_indextoname: function() {
invocations++;

if(invocations == 1) {
return interfaceName;
}

threwException = true;
throw new Error("Panic!");
},
// and stub DNSServiceBrowse to expose a reference to the passed callback
DNSServiceBrowse: function(sdRef, flags, ifaceIdx, serviceType, domain, on_service_changed, context) {
callback = function() {
// pass 1 as the interface index so we don't try to find the name for loopback
on_service_changed(sdRef, flags, 1, dns_sd.kDNSServiceErr_NoError, serviceName, serviceType, domain, context);
};
}
};

// we're going to expect two invocations, one where the interface is present and one where it's not
var serviceDownInvocations = 0;

// create the browser with our mock of dns_sd
var browser = proxyquire('../lib/browser.js', { './dns_sd': mock_dns_sd }).Browser.create(serviceName);
browser.on("serviceDown", function(service) {
serviceDownInvocations++;

if(serviceDownInvocations == 1) {
// first invocation, should have interface name from dns_sd callback
test.equal(service.networkInterface, interfaceName);

// should not have thrown an exception yet
test.ok( ! threwException);
}

if(serviceDownInvocations == 2) {
// second invocation, should have thrown an exception in the callback
test.ok(threwException);

// should still have the interface name even though we threw an exception
test.equal(service.networkInterface, interfaceName);

test.done();
}
});

// simulate two MDNS events, this will trigger the serviceDown event we listen for above.
callback();
callback();
}
}