Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion examples/example4.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ var onvif = require('../lib/onvif');
var xml2js = require('xml2js')
var stripPrefix = require('xml2js').processors.stripPrefix;

let found = [];

/*
onvif.Discovery.on('device', function(cam,rinfo,xml){
// function will be called as soon as NVT responds
Expand Down Expand Up @@ -47,11 +49,26 @@ onvif.Discovery.on('device', function(cam, rinfo, xml) {
}
let msg = 'Discovery Reply from ' + rinfo.address + ' (' + name + ') (' + hardware + ') (' + xaddrs + ') (' + urn + ')';
console.log(msg);
found.push(msg);
}
);
})
onvif.Discovery.on('error', function(err,xml) {
// The ONVIF library had problems parsing some XML
console.log('Discovery error ' + err);
});
onvif.Discovery.probe();
onvif.Discovery.on('sending', function(interface, localaddress, localport) {
console.log("Sending Discovery to " + interface + " from " + localaddress + ":" + localport);
});

const options = {
timeout: 3000,
buffer: 20 * 1024 * 1024,
};

onvif.Discovery.probe(options, probeFinishedCallback);

function probeFinishedCallback(err, cams) {
console.log("Found " + found.length + " device(s)");
console.log(found.sort());
}
2 changes: 1 addition & 1 deletion lib/cam.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ Cam.prototype._requestPart2 = function(options, callback) {
// Re-request with digest auth header
res.destroy();
options.headers.Authorization = _this.digestAuth(wwwAuthenticate, reqOptions);
_this._requestPart2(options, callback);
return _this._requestPart2(options, callback);
}
const bufs = [];
let length = 0;
Expand Down
99 changes: 55 additions & 44 deletions lib/discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const
linerase = require('./utils').linerase,
parseSOAPString = require('./utils').parseSOAPString,
url = require('url'),
os = require('os');
os = require('os'),
dgram = require('dgram');

/**
* Discovery singleton
Expand Down Expand Up @@ -88,14 +89,7 @@ Discovery.probe = function(options, callback) {
'</Probe>' +
'</Body>' +
'</Envelope>'
),
// create a socket with reuse address option, in case there is many nodde processes listening on the same port
socket = require('dgram').createSocket('udp4', { reuseAddr: true });

socket.on('error', function(err) {
Discovery.emit('error', err);
callback(err);
});
);

const httpOK200 = 200;
const listener = function(msg, rinfo) {
Expand Down Expand Up @@ -151,46 +145,63 @@ Discovery.probe = function(options, callback) {
});
};

// Callback function to bind the socket to the interface
const bindingCallback = function(err) {
if (err) {
Discovery.emit('error', err);
callback(err);
} else {
// set buffer size to the buffer size option in bytes
if (options.bufferSize && options.bufferSize > 0) {
socket.setRecvBufferSize(options.bufferSize);
}
socket.send(request, 0, request.length, 3702, '239.255.255.250');
// Try all network interfaces and all IP addresses
const interfaces = os.networkInterfaces();
for (const interface in interfaces) {
// Check if we are senidng Discovery from a specific Interface name
if (options.device !== undefined && options.device !== interface) {
continue;
}
};
// If device is specified try to bind to that interface
var shouldBind = false;
if (options.device) {
var interfaces = os.networkInterfaces();
// Try to find the interface based on the device name
if (options.device in interfaces) {
interfaces[options.device].some(function(address) {
// Only use IPv4 addresses
if (address.family === 'IPv4') {
socket.bind(options.listeningPort || null, address.address, bindingCallback);
shouldBind = true;
return true;
}
});
}
}
for (const addressItem of interfaces[interface]) {
// Suggestion from @bloggy - Check if we are senidng Discivery from a specific IP address
if (options.bindAddress !== undefined && options.bindAddress !== addressItem.address) {
continue;
}

// If no device is specified, bind to the default port
if (!shouldBind) {
socket.bind(options.listeningPort || null, bindingCallback);
}
// Allow Loopback
// We could check 'addressItem.internal' but we may be running on the same device as a ONVIF NVR (eg the RPOS ONVIF Server project)

// Only use IPv4 addresses
if (addressItem.family === 'IPv4') {
// create a socket with reuse address option, in case there is many nodde processes listening on the same port
let socket = dgram.createSocket('udp4', { reuseAddr: true });

// Uses a "Closure" so that the 'socket' in the callback refers to the Socket we just created
const bindingCallback = function(err) {
if (err) {
Discovery.emit('error', err);
} else {
// set buffer size to the buffer size option in bytes
if (options.bufferSize && options.bufferSize > 0) {
socket.setRecvBufferSize(options.bufferSize);
}
Discovery.emit('sending', interface, socket.address().address, socket.address().port);
socket.send(request, 0, request.length, 3702, '239.255.255.250');


}
};

socket.on('error', function(err) {
Discovery.emit('error', err);
});

socket.on('message', listener);

socket.on('message', listener);
socket.bind(options.listeningPort || null, addressItem.address, bindingCallback);

// timeout to close the socket
setTimeout(function() {
socket.removeListener('message', listener);
socket.close();
}, options.timeout || 5000);

}
}
}

// timeout to send the reply via the callback function
setTimeout(function() {
socket.removeListener('message', listener);
socket.close();
callback(errors.length ? errors : null, Object.keys(cams).map(function(addr) { return cams[addr]; }));
}.bind(this), options.timeout || 5000);
};
Expand Down