adding new files
This commit is contained in:
parent
77f8a803a3
commit
da7d8e3763
|
@ -0,0 +1,53 @@
|
|||
mDNS Documentation
|
||||
|
||||
What is mDNS?
|
||||
|
||||
mDNS stands for Multicast Domain Name System. It's function is to resolve host names to IP addresses within small networkds that do not include a local name server. It is a zero-configuration service, using essentially the same programming interfaces, packet formats and operating semantics as the unicast Domain Name System (DNS). Although mDNS is designed to be stand-alone capable, it can work in concert with unicast DNS servers.
|
||||
|
||||
Full documentation of the protocol is located at: https://tools.ietf.org/html/rfc6762
|
||||
|
||||
Other helpful topics and documents:
|
||||
|
||||
- Zero Configuration Networking: https://tools.ietf.org/html/rfc6762#ref-Zeroconf
|
||||
- Automatic link-local addressing: https://tools.ietf.org/html/rfc3927
|
||||
|
||||
https://tools.ietf.org/html/rfc4862
|
||||
|
||||
|
||||
DNS-format messages contain a header, a Question Section, then Answer, Authority, and additional Record Sections. The Answer, Authority, and Additional Record Sections all hold resource records.
|
||||
|
||||
|
||||
mDNS is a datagram protocal that uses broadcast mode and membership groups.
|
||||
|
||||
|
||||
|
||||
What does mDNS in the Daplie System?
|
||||
|
||||
We are sending messages back and forth on a network that searches for any other mDNS compatible devices and asks that device if it is connected to a router or WiFi with a Daplie-compatible Cloud device.
|
||||
|
||||
If it is a Daplie-compatible Cloud device, then it will reply to the sender with some sort of confirmation.
|
||||
|
||||
|
||||
|
||||
Terms:
|
||||
|
||||
TTL - IP Time to Live - located in IP header of the DNS packet and is used effectively as a hop-count limit for the packet, to guard against routing loops
|
||||
|
||||
|
||||
"shared" resource record set is where several Multicast DNS responders may have records with the same name, rrtype, and rrclass, and several responders may respond to a particular query
|
||||
|
||||
"unique" resource record set is one where all the records with that name, rrtype, and rrclass are conceptually under the control or ownership of a single responder, and it is expected that at most one responder should respond to a query for that name, rrtype, and rrclass. Before claiming ownership of a unique resource record set, a responder MUST probe to verify that no other responder already claims ownership. (For fault-tolerance and other reasons, sometimes it is permissible to have more than one responder answering for a particular "unique" resource record set, but such cooperating resoinders MUST give answers containing identical rdata for these records. If they do not give answers containing identical rdata, then the probing stop will reject the data as being inconsistent with what is already being advertised on the network for these names.)
|
||||
|
||||
|
||||
Multicast DNS Names
|
||||
|
||||
A host that belongs to an organization or individual who has control over some potion of the DNS namespace can be assigned a globally unique name within that portion of th DNS namespace, such as, "chechire.example.com". For those of us who have this luxury, this works very well. However, the mojority of home computer users do not have easy access to any portion of the global DNS namespace within which they have the authoriry to create names. This leaves the majority of home computers effectively anonymous for practical purposes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
'use strict';
|
||||
|
||||
module.exports.respond = function (socket, packets, rinfo) {
|
||||
var dns = require('dns-js');
|
||||
var os = require('os');
|
||||
var queryname = '_cloud._tcp.local';
|
||||
|
||||
console.log(packets);
|
||||
|
||||
packets.forEach(function (packet) {
|
||||
packet.question.forEach(function (q) {
|
||||
if (queryname !== q.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('question', q.name, q.typeName, q.className, q.flag, q);
|
||||
var rpacket = new dns.DNSPacket();
|
||||
var ifaces = os.networkInterfaces();
|
||||
//var llRe = /^(fe80|169)/i; // link-local
|
||||
|
||||
Object.keys(ifaces).forEach(function (iname) {
|
||||
var iface = ifaces[iname];
|
||||
|
||||
iface = iface.filter(function (pface) {
|
||||
// nix loopback, internal and ipv6 link-local (non-routable) and ipv4 link-local
|
||||
return !pface.internal;// && !(pface.scopeid > 1) && !llRe.test(pface.address);
|
||||
});
|
||||
|
||||
iface.forEach(function (pface) {
|
||||
rpacket.additional.push({
|
||||
name: q.name
|
||||
, type: ('IPv4' === pface.family ? dns.DNSRecord.Type.A : dns.DNSRecord.Type.AAAA)
|
||||
, ttl: 10
|
||||
, class: dns.DNSRecord.Class.IN
|
||||
, address: pface.address // '_workstation._tcp.local'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var myRndId = 'be1af7a';
|
||||
rpacket.answer.push({
|
||||
name: q.name
|
||||
, type: dns.DNSRecord.Type.PTR
|
||||
, ttl: 10
|
||||
, class: dns.DNSRecord.Class.IN
|
||||
, data: myRndId + '.' + queryname
|
||||
});
|
||||
rpacket.question.push(new dns.DNSRecord(
|
||||
queryname // Name
|
||||
, dns.DNSRecord.Type.PTR // Type
|
||||
, dns.DNSRecord.Class.IN // Class
|
||||
//, null // TTL
|
||||
));
|
||||
rpacket.additional.push({
|
||||
name: myRndId + '.' + queryname
|
||||
, type: dns.DNSRecord.Type.SRV
|
||||
, ttl: 10
|
||||
, class: dns.DNSRecord.Class.IN
|
||||
, priority: 0
|
||||
, weight: 0
|
||||
, port: 443
|
||||
, target: myRndId + ".local"
|
||||
});
|
||||
rpacket.additional.push({
|
||||
name: myRndId + '.' + '_device-info._tcp.local'
|
||||
, type: dns.DNSRecord.Type.TXT
|
||||
, ttl: 10
|
||||
, class: dns.DNSRecord.Class.IN
|
||||
, data: ["model=CloudHome1,1", "dappsvers=1"]
|
||||
});
|
||||
rpacket.header.id = packet.header.id;
|
||||
rpacket.header.aa = 1;
|
||||
rpacket.header.qr = 1;
|
||||
rpacket.header.rd = 0;
|
||||
|
||||
console.log('');
|
||||
console.log('START JSON PACKET');
|
||||
console.log(rpacket);
|
||||
var buf = dns.DNSPacket.toBuffer(rpacket);
|
||||
console.log(buf.toString('hex'));
|
||||
console.log('END JSON PACKET');
|
||||
console.log('');
|
||||
|
||||
console.log('');
|
||||
console.log('START DNS PACKET');
|
||||
var pkt = dns.DNSPacket.parse(buf);
|
||||
console.log(pkt);
|
||||
console.log('END DNS PACKET');
|
||||
console.log('');
|
||||
socket.send(buf, rinfo.port, rinfo.address);
|
||||
});
|
||||
/*
|
||||
*/
|
||||
packet.answer.forEach(function (a) {
|
||||
console.log('answer', a.name, a.typeName, a.className, a.flag, a);
|
||||
});
|
||||
packet.authority.forEach(function (a) {
|
||||
console.log('authority', a.name, a.typeName, a.className, a.flag, a);
|
||||
});
|
||||
packet.additional.forEach(function (a) {
|
||||
console.log('additional', a.name, a.typeName, a.className, a.flag, a);
|
||||
});
|
||||
});
|
||||
console.log('\n');
|
||||
};
|
4
howto.md
4
howto.md
|
@ -6,5 +6,9 @@ header
|
|||
npm init
|
||||
|
||||
|
||||
|
||||
how to duplicate DNS crash:
|
||||
|
||||
|
||||
How to print out hex and binary values of the message?
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
var os = require('os');
|
||||
|
||||
var ifaces = os.networkInterfaces();
|
||||
var llRe = /^(fe80|169)/i; // link-local
|
||||
|
||||
Object.keys(ifaces).forEach(function (iname) {
|
||||
var iface = ifaces[iname];
|
||||
|
||||
iface = iface.filter(function (pface) {
|
||||
// nix loopback, internal and ipv6 link-local (non-routable) and ipv4 link-local
|
||||
return !pface.internal && !(pface.scopeid > 1) && !llRe.test(pface.address);
|
||||
});
|
||||
|
||||
iface.forEach(function (pface) {
|
||||
console.log(pface);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
|
||||
var dgram = require('dgram');
|
||||
var socket = dgram.createSocket({
|
||||
type: 'udp4'
|
||||
, reuseAddr: true
|
||||
});
|
||||
var dns = require('dns-js');
|
||||
//var DNSPacket = dns.DNSPacket;
|
||||
|
||||
var broadcast = '224.0.0.251'; // mdns
|
||||
var port = 5353; // mdns
|
||||
|
||||
socket.on('message', function (message, rinfo) {
|
||||
console.log('Received %d bytes from %s:%d\n',
|
||||
message.length, rinfo.address, rinfo.port);
|
||||
//console.log(msg.toString('utf8'));
|
||||
|
||||
console.log(message.toString('hex'));
|
||||
var packets;
|
||||
|
||||
try {
|
||||
packets = dns.DNSPacket.parse(message);
|
||||
}
|
||||
catch (er) {
|
||||
//partial, skip it
|
||||
console.error(er);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(packets)) { packets = [packets]; }
|
||||
|
||||
require('./cloud-respond.js').respond(socket, packets, rinfo);
|
||||
});
|
||||
|
||||
socket.bind(port, function () {
|
||||
console.log('bound on', port);
|
||||
console.log('bound on', this.address());
|
||||
|
||||
socket.setBroadcast(true);
|
||||
socket.addMembership(broadcast);
|
||||
|
||||
// buf.forEach parseInt(byte.toString('hex'), 16).toString(2);
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
Dave Eddy <dave@daveeddy.com>
|
||||
Fred Kuo <fred.kuo@joyent.com>
|
||||
Lars-Magnus Skog <ralphtheninja@riseup.net>
|
||||
Mark Cavage <mcavage@gmail.com>
|
||||
Patrick Mooney <pmooney@pfmooney.com>
|
||||
Rob Gulewich <robert.gulewich@joyent.com>
|
|
@ -0,0 +1,14 @@
|
|||
# assert-plus Changelog
|
||||
|
||||
## 1.0.0
|
||||
|
||||
- *BREAKING* assert.number (and derivatives) now accept Infinity as valid input
|
||||
- Add assert.finite check. Previous assert.number callers should use this if
|
||||
they expect Infinity inputs to throw.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
- Fix `assert.object(null)` so it throws
|
||||
- Fix optional/arrayOf exports for non-type-of asserts
|
||||
- Add optiona/arrayOf exports for Stream/Date/Regex/uuid
|
||||
- Add basic unit test coverage
|
|
@ -0,0 +1,162 @@
|
|||
# assert-plus
|
||||
|
||||
This library is a super small wrapper over node's assert module that has two
|
||||
things: (1) the ability to disable assertions with the environment variable
|
||||
NODE\_NDEBUG, and (2) some API wrappers for argument testing. Like
|
||||
`assert.string(myArg, 'myArg')`. As a simple example, most of my code looks
|
||||
like this:
|
||||
|
||||
```javascript
|
||||
var assert = require('assert-plus');
|
||||
|
||||
function fooAccount(options, callback) {
|
||||
assert.object(options, 'options');
|
||||
assert.number(options.id, 'options.id');
|
||||
assert.bool(options.isManager, 'options.isManager');
|
||||
assert.string(options.name, 'options.name');
|
||||
assert.arrayOfString(options.email, 'options.email');
|
||||
assert.func(callback, 'callback');
|
||||
|
||||
// Do stuff
|
||||
callback(null, {});
|
||||
}
|
||||
```
|
||||
|
||||
# API
|
||||
|
||||
All methods that *aren't* part of node's core assert API are simply assumed to
|
||||
take an argument, and then a string 'name' that's not a message; `AssertionError`
|
||||
will be thrown if the assertion fails with a message like:
|
||||
|
||||
AssertionError: foo (string) is required
|
||||
at test (/home/mark/work/foo/foo.js:3:9)
|
||||
at Object.<anonymous> (/home/mark/work/foo/foo.js:15:1)
|
||||
at Module._compile (module.js:446:26)
|
||||
at Object..js (module.js:464:10)
|
||||
at Module.load (module.js:353:31)
|
||||
at Function._load (module.js:311:12)
|
||||
at Array.0 (module.js:484:10)
|
||||
at EventEmitter._tickCallback (node.js:190:38)
|
||||
|
||||
from:
|
||||
|
||||
```javascript
|
||||
function test(foo) {
|
||||
assert.string(foo, 'foo');
|
||||
}
|
||||
```
|
||||
|
||||
There you go. You can check that arrays are of a homogeneous type with `Arrayof$Type`:
|
||||
|
||||
```javascript
|
||||
function test(foo) {
|
||||
assert.arrayOfString(foo, 'foo');
|
||||
}
|
||||
```
|
||||
|
||||
You can assert IFF an argument is not `undefined` (i.e., an optional arg):
|
||||
|
||||
```javascript
|
||||
assert.optionalString(foo, 'foo');
|
||||
```
|
||||
|
||||
Lastly, you can opt-out of assertion checking altogether by setting the
|
||||
environment variable `NODE_NDEBUG=1`. This is pseudo-useful if you have
|
||||
lots of assertions, and don't want to pay `typeof ()` taxes to v8 in
|
||||
production. Be advised: The standard functions re-exported from `assert` are
|
||||
also disabled in assert-plus if NDEBUG is specified. Using them directly from
|
||||
the `assert` module avoids this behavior.
|
||||
|
||||
The complete list of APIs is:
|
||||
|
||||
* assert.array
|
||||
* assert.bool
|
||||
* assert.buffer
|
||||
* assert.func
|
||||
* assert.number
|
||||
* assert.finite
|
||||
* assert.object
|
||||
* assert.string
|
||||
* assert.stream
|
||||
* assert.date
|
||||
* assert.regexp
|
||||
* assert.uuid
|
||||
* assert.arrayOfArray
|
||||
* assert.arrayOfBool
|
||||
* assert.arrayOfBuffer
|
||||
* assert.arrayOfFunc
|
||||
* assert.arrayOfNumber
|
||||
* assert.arrayOfFinite
|
||||
* assert.arrayOfObject
|
||||
* assert.arrayOfString
|
||||
* assert.arrayOfStream
|
||||
* assert.arrayOfDate
|
||||
* assert.arrayOfRegexp
|
||||
* assert.arrayOfUuid
|
||||
* assert.optionalArray
|
||||
* assert.optionalBool
|
||||
* assert.optionalBuffer
|
||||
* assert.optionalFunc
|
||||
* assert.optionalNumber
|
||||
* assert.optionalFinite
|
||||
* assert.optionalObject
|
||||
* assert.optionalString
|
||||
* assert.optionalStream
|
||||
* assert.optionalDate
|
||||
* assert.optionalRegexp
|
||||
* assert.optionalUuid
|
||||
* assert.optionalArrayOfArray
|
||||
* assert.optionalArrayOfBool
|
||||
* assert.optionalArrayOfBuffer
|
||||
* assert.optionalArrayOfFunc
|
||||
* assert.optionalArrayOfNumber
|
||||
* assert.optionalArrayOfFinite
|
||||
* assert.optionalArrayOfObject
|
||||
* assert.optionalArrayOfString
|
||||
* assert.optionalArrayOfStream
|
||||
* assert.optionalArrayOfDate
|
||||
* assert.optionalArrayOfRegexp
|
||||
* assert.optionalArrayOfUuid
|
||||
* assert.AssertionError
|
||||
* assert.fail
|
||||
* assert.ok
|
||||
* assert.equal
|
||||
* assert.notEqual
|
||||
* assert.deepEqual
|
||||
* assert.notDeepEqual
|
||||
* assert.strictEqual
|
||||
* assert.notStrictEqual
|
||||
* assert.throws
|
||||
* assert.doesNotThrow
|
||||
* assert.ifError
|
||||
|
||||
# Installation
|
||||
|
||||
npm install assert-plus
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2012 Mark Cavage
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## Bugs
|
||||
|
||||
See <https://github.com/mcavage/node-assert-plus/issues>.
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright (c) 2012, Mark Cavage. All rights reserved.
|
||||
// Copyright 2015 Joyent, Inc.
|
||||
|
||||
var assert = require('assert');
|
||||
var Stream = require('stream').Stream;
|
||||
var util = require('util');
|
||||
|
||||
|
||||
///--- Globals
|
||||
|
||||
/* JSSTYLED */
|
||||
var UUID_REGEXP = /^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$/;
|
||||
|
||||
|
||||
///--- Internal
|
||||
|
||||
function _capitalize(str) {
|
||||
return (str.charAt(0).toUpperCase() + str.slice(1));
|
||||
}
|
||||
|
||||
function _toss(name, expected, oper, arg, actual) {
|
||||
throw new assert.AssertionError({
|
||||
message: util.format('%s (%s) is required', name, expected),
|
||||
actual: (actual === undefined) ? typeof (arg) : actual(arg),
|
||||
expected: expected,
|
||||
operator: oper || '===',
|
||||
stackStartFunction: _toss.caller
|
||||
});
|
||||
}
|
||||
|
||||
function _getClass(arg) {
|
||||
return (Object.prototype.toString.call(arg).slice(8, -1));
|
||||
}
|
||||
|
||||
function noop() {
|
||||
// Why even bother with asserts?
|
||||
}
|
||||
|
||||
|
||||
///--- Exports
|
||||
|
||||
var types = {
|
||||
bool: {
|
||||
check: function (arg) { return typeof (arg) === 'boolean'; }
|
||||
},
|
||||
func: {
|
||||
check: function (arg) { return typeof (arg) === 'function'; }
|
||||
},
|
||||
string: {
|
||||
check: function (arg) { return typeof (arg) === 'string'; }
|
||||
},
|
||||
object: {
|
||||
check: function (arg) {
|
||||
return typeof (arg) === 'object' && arg !== null;
|
||||
}
|
||||
},
|
||||
number: {
|
||||
check: function (arg) {
|
||||
return typeof (arg) === 'number' && !isNaN(arg);
|
||||
}
|
||||
},
|
||||
finite: {
|
||||
check: function (arg) {
|
||||
return typeof (arg) === 'number' && !isNaN(arg) && isFinite(arg);
|
||||
}
|
||||
},
|
||||
buffer: {
|
||||
check: function (arg) { return Buffer.isBuffer(arg); },
|
||||
operator: 'Buffer.isBuffer'
|
||||
},
|
||||
array: {
|
||||
check: function (arg) { return Array.isArray(arg); },
|
||||
operator: 'Array.isArray'
|
||||
},
|
||||
stream: {
|
||||
check: function (arg) { return arg instanceof Stream; },
|
||||
operator: 'instanceof',
|
||||
actual: _getClass
|
||||
},
|
||||
date: {
|
||||
check: function (arg) { return arg instanceof Date; },
|
||||
operator: 'instanceof',
|
||||
actual: _getClass
|
||||
},
|
||||
regexp: {
|
||||
check: function (arg) { return arg instanceof RegExp; },
|
||||
operator: 'instanceof',
|
||||
actual: _getClass
|
||||
},
|
||||
uuid: {
|
||||
check: function (arg) {
|
||||
return typeof (arg) === 'string' && UUID_REGEXP.test(arg);
|
||||
},
|
||||
operator: 'isUUID'
|
||||
}
|
||||
};
|
||||
|
||||
function _setExports(ndebug) {
|
||||
var keys = Object.keys(types);
|
||||
var out;
|
||||
|
||||
/* re-export standard assert */
|
||||
if (process.env.NODE_NDEBUG) {
|
||||
out = noop;
|
||||
} else {
|
||||
out = function (arg, msg) {
|
||||
if (!arg) {
|
||||
_toss(msg, 'true', arg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* standard checks */
|
||||
keys.forEach(function (k) {
|
||||
if (ndebug) {
|
||||
out[k] = noop;
|
||||
return;
|
||||
}
|
||||
var type = types[k];
|
||||
out[k] = function (arg, msg) {
|
||||
if (!type.check(arg)) {
|
||||
_toss(msg, k, type.operator, arg, type.actual);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/* optional checks */
|
||||
keys.forEach(function (k) {
|
||||
var name = 'optional' + _capitalize(k);
|
||||
if (ndebug) {
|
||||
out[name] = noop;
|
||||
return;
|
||||
}
|
||||
var type = types[k];
|
||||
out[name] = function (arg, msg) {
|
||||
if (arg === undefined || arg === null) {
|
||||
return;
|
||||
}
|
||||
if (!type.check(arg)) {
|
||||
_toss(msg, k, type.operator, arg, type.actual);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/* arrayOf checks */
|
||||
keys.forEach(function (k) {
|
||||
var name = 'arrayOf' + _capitalize(k);
|
||||
if (ndebug) {
|
||||
out[name] = noop;
|
||||
return;
|
||||
}
|
||||
var type = types[k];
|
||||
var expected = '[' + k + ']';
|
||||
out[name] = function (arg, msg) {
|
||||
if (!Array.isArray(arg)) {
|
||||
_toss(msg, expected, type.operator, arg, type.actual);
|
||||
}
|
||||
var i;
|
||||
for (i = 0; i < arg.length; i++) {
|
||||
if (!type.check(arg[i])) {
|
||||
_toss(msg, expected, type.operator, arg, type.actual);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/* optionalArrayOf checks */
|
||||
keys.forEach(function (k) {
|
||||
var name = 'optionalArrayOf' + _capitalize(k);
|
||||
if (ndebug) {
|
||||
out[name] = noop;
|
||||
return;
|
||||
}
|
||||
var type = types[k];
|
||||
var expected = '[' + k + ']';
|
||||
out[name] = function (arg, msg) {
|
||||
if (arg === undefined || arg === null) {
|
||||
return;
|
||||
}
|
||||
if (!Array.isArray(arg)) {
|
||||
_toss(msg, expected, type.operator, arg, type.actual);
|
||||
}
|
||||
var i;
|
||||
for (i = 0; i < arg.length; i++) {
|
||||
if (!type.check(arg[i])) {
|
||||
_toss(msg, expected, type.operator, arg, type.actual);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/* re-export built-in assertions */
|
||||
Object.keys(assert).forEach(function (k) {
|
||||
if (k === 'AssertionError') {
|
||||
out[k] = assert[k];
|
||||
return;
|
||||
}
|
||||
if (ndebug) {
|
||||
out[k] = noop;
|
||||
return;
|
||||
}
|
||||
out[k] = assert[k];
|
||||
});
|
||||
|
||||
/* export ourselves (for unit tests _only_) */
|
||||
out._setExports = _setExports;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
module.exports = _setExports(process.env.NODE_NDEBUG);
|
|
@ -0,0 +1,115 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "assert-plus@^1.0.0",
|
||||
"scope": null,
|
||||
"escapedName": "assert-plus",
|
||||
"name": "assert-plus",
|
||||
"rawSpec": "^1.0.0",
|
||||
"spec": ">=1.0.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"/srv/demos/node_modules/verror"
|
||||
]
|
||||
],
|
||||
"_from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"_id": "assert-plus@1.0.0",
|
||||
"_inCache": true,
|
||||
"_location": "/assert-plus",
|
||||
"_nodeVersion": "0.10.40",
|
||||
"_npmUser": {
|
||||
"name": "pfmooney",
|
||||
"email": "patrick.f.mooney@gmail.com"
|
||||
},
|
||||
"_npmVersion": "3.3.9",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "assert-plus@^1.0.0",
|
||||
"scope": null,
|
||||
"escapedName": "assert-plus",
|
||||
"name": "assert-plus",
|
||||
"rawSpec": "^1.0.0",
|
||||
"spec": ">=1.0.0 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/verror"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"_shasum": "f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "assert-plus@^1.0.0",
|
||||
"_where": "/srv/demos/node_modules/verror",
|
||||
"author": {
|
||||
"name": "Mark Cavage",
|
||||
"email": "mcavage@gmail.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/mcavage/node-assert-plus/issues"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Dave Eddy",
|
||||
"email": "dave@daveeddy.com"
|
||||
},
|
||||
{
|
||||
"name": "Fred Kuo",
|
||||
"email": "fred.kuo@joyent.com"
|
||||
},
|
||||
{
|
||||
"name": "Lars-Magnus Skog",
|
||||
"email": "ralphtheninja@riseup.net"
|
||||
},
|
||||
{
|
||||
"name": "Mark Cavage",
|
||||
"email": "mcavage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Patrick Mooney",
|
||||
"email": "pmooney@pfmooney.com"
|
||||
},
|
||||
{
|
||||
"name": "Rob Gulewich",
|
||||
"email": "robert.gulewich@joyent.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {},
|
||||
"description": "Extra assertions on top of node's assert module",
|
||||
"devDependencies": {
|
||||
"faucet": "0.0.1",
|
||||
"tape": "4.2.2"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525",
|
||||
"tarball": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
},
|
||||
"homepage": "https://github.com/mcavage/node-assert-plus#readme",
|
||||
"license": "MIT",
|
||||
"main": "./assert.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "mcavage",
|
||||
"email": "mcavage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "pfmooney",
|
||||
"email": "patrick.f.mooney@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "assert-plus",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mcavage/node-assert-plus.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tape tests/*.js | ./node_modules/.bin/faucet"
|
||||
},
|
||||
"version": "1.0.0"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
*.dot
|
||||
*.gif
|
||||
node_modules
|
|
@ -0,0 +1,43 @@
|
|||
BinaryHeap
|
||||
==========
|
||||
|
||||
Basic binary heap tree using linked lists
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```javascript
|
||||
var BinaryHeap = require('binaryheap');
|
||||
var heap = new BinaryHeap();
|
||||
|
||||
var a = [6, 5, 3, 1, 8, 7, 2, 4];
|
||||
|
||||
a.forEach(function (k) {
|
||||
heap.insert({ value: k }, k);
|
||||
});
|
||||
|
||||
heap.print();
|
||||
|
||||
while (heap.length) {
|
||||
console.log('popping', heap.pop().value);
|
||||
}
|
||||
```
|
||||
|
||||
By default it stores as a max-heap, if you pass truthy to the constructor though
|
||||
it will behave as a min-heap.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
* `insert(obj, key)` -- obj can be any new or existing object, and key is any
|
||||
value that behaves sanely with `>` or `<`
|
||||
* `pop()` -- removes and returns the maximum or minimum object from the root
|
||||
of the heap
|
||||
* `remove(obj)` -- removes a previously inserted object from the heap
|
||||
* `print()` -- mostly for debugging purposes prints a graphviz dot style
|
||||
digraph to confirm ordering
|
||||
|
||||
Members
|
||||
-------
|
||||
|
||||
* `length` -- number of objects currently in the heap
|
|
@ -0,0 +1,313 @@
|
|||
// Copyright 2012 Timothy J Fontaine <tjfontaine@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var Heap = function(min) {
|
||||
this.length = 0;
|
||||
this.root = undefined;
|
||||
if (min) {
|
||||
this._comparator = this._smallest;
|
||||
} else {
|
||||
this._comparator = this._largest;
|
||||
}
|
||||
};
|
||||
|
||||
Heap.init = function(obj, key) {
|
||||
obj._parent = null;
|
||||
obj._left = null;
|
||||
obj._right = null;
|
||||
obj._key = key;
|
||||
return obj;
|
||||
};
|
||||
|
||||
Heap.prototype.count = function (node) {
|
||||
if (!node) return 0;
|
||||
|
||||
var c = 1;
|
||||
|
||||
c += this.count(node._left);
|
||||
c += this.count(node._right);
|
||||
|
||||
return c;
|
||||
};
|
||||
|
||||
Heap.prototype.insert = function(obj, key) {
|
||||
var insert, node;
|
||||
|
||||
this.length += 1;
|
||||
|
||||
node = Heap.init(obj, key);
|
||||
|
||||
if (!this.root) {
|
||||
this.root = node;
|
||||
} else {
|
||||
insert = this._last();
|
||||
|
||||
node._parent = insert;
|
||||
|
||||
if (!insert._left)
|
||||
insert._left = node;
|
||||
else
|
||||
insert._right = node;
|
||||
|
||||
this._up(node);
|
||||
}
|
||||
|
||||
this._head();
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
Heap.prototype.pop = function() {
|
||||
var ret, last;
|
||||
|
||||
if (!this.root)
|
||||
return null;
|
||||
|
||||
return this.remove(this.root);
|
||||
};
|
||||
|
||||
Heap.prototype.remove = function(node) {
|
||||
var ret, last;
|
||||
|
||||
ret = node;
|
||||
last = this._last();
|
||||
|
||||
if (last._right)
|
||||
last = last._right;
|
||||
else
|
||||
last = last._left;
|
||||
|
||||
this.length -= 1;
|
||||
|
||||
if (!last) {
|
||||
if (ret == this.root)
|
||||
this.root = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == last) {
|
||||
if (ret._parent._left == node)
|
||||
ret._parent._left = null;
|
||||
else
|
||||
ret._parent._right = null;
|
||||
last = ret._parent;
|
||||
ret._parent = null;
|
||||
} else if (!ret._left && !ret._right) {
|
||||
// we're trying to remove an element without any children and its not the last
|
||||
// move the last under its parent and heap-up
|
||||
if (last._parent._left == last) last._parent._left = null;
|
||||
else last._parent._right = null;
|
||||
|
||||
if (ret._parent._left == ret) ret._parent._left = last;
|
||||
else ret._parent._right = last;
|
||||
|
||||
last._parent = ret._parent;
|
||||
|
||||
ret._parent = null;
|
||||
|
||||
// TODO in this case we shouldn't later also do a down, but it should only visit once
|
||||
this._up(last);
|
||||
} else {
|
||||
this._delete_swap(ret, last);
|
||||
}
|
||||
|
||||
if (ret == this.root)
|
||||
this.root = last;
|
||||
|
||||
this._down(last);
|
||||
this._head();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
// TODO this probably isn't the most efficient way to ensure that we're always
|
||||
// at the root of the tree, but it works for now
|
||||
Heap.prototype._head = function() {
|
||||
if (!this.root)
|
||||
return;
|
||||
|
||||
var tmp = this.root;
|
||||
while (tmp._parent) {
|
||||
tmp = tmp._parent;
|
||||
}
|
||||
|
||||
this.root = tmp;
|
||||
};
|
||||
|
||||
// TODO is there a more efficient way to store this instead of an array?
|
||||
Heap.prototype._last = function() {
|
||||
var path, pos, mod, insert;
|
||||
|
||||
pos = this.length;
|
||||
path = [];
|
||||
while (pos > 1) {
|
||||
mod = pos % 2;
|
||||
pos = Math.floor(pos / 2);
|
||||
path.push(mod);
|
||||
}
|
||||
|
||||
insert = this.root;
|
||||
|
||||
while (path.length > 1) {
|
||||
pos = path.pop();
|
||||
if (pos === 0)
|
||||
insert = insert._left;
|
||||
else
|
||||
insert = insert._right;
|
||||
}
|
||||
|
||||
return insert;
|
||||
};
|
||||
|
||||
Heap.prototype._swap = function(a, b) {
|
||||
var cleft, cright, tparent;
|
||||
|
||||
cleft = b._left;
|
||||
cright = b._right;
|
||||
|
||||
if (a._parent) {
|
||||
if (a._parent._left == a) a._parent._left = b;
|
||||
else a._parent._right = b;
|
||||
}
|
||||
|
||||
b._parent = a._parent;
|
||||
a._parent = b;
|
||||
|
||||
// This assumes direct descendents
|
||||
if (a._left == b) {
|
||||
b._left = a;
|
||||
b._right = a._right;
|
||||
if (b._right) b._right._parent = b;
|
||||
} else {
|
||||
b._right = a;
|
||||
b._left = a._left;
|
||||
if (b._left) b._left._parent = b;
|
||||
}
|
||||
|
||||
a._left = cleft;
|
||||
a._right = cright;
|
||||
|
||||
if (a._left) a._left._parent = a;
|
||||
if (a._right) a._right._parent = a;
|
||||
|
||||
assert.notEqual(a._parent, a, "A shouldn't refer to itself");
|
||||
assert.notEqual(b._parent, b, "B shouldn't refer to itself");
|
||||
};
|
||||
|
||||
Heap.prototype._delete_swap = function(a, b) {
|
||||
if (a._left != b) b._left = a._left;
|
||||
if (a._right != b) b._right = a._right;
|
||||
|
||||
if (b._parent._left == b) b._parent._left = null;
|
||||
else b._parent._right = null;
|
||||
|
||||
if (a._parent) {
|
||||
if (a._parent._left == a) a._parent._left = b;
|
||||
else a._parent._right = b;
|
||||
}
|
||||
|
||||
b._parent = a._parent;
|
||||
|
||||
if (b._left) b._left._parent = b;
|
||||
if (b._right) b._right._parent = b;
|
||||
|
||||
a._parent = null;
|
||||
a._left = null;
|
||||
a._right = null;
|
||||
};
|
||||
|
||||
Heap.prototype._smallest = function(heap) {
|
||||
var small = heap;
|
||||
|
||||
if (heap._left && heap._key > heap._left._key) {
|
||||
small = heap._left;
|
||||
}
|
||||
|
||||
if (heap._right && small._key > heap._right._key) {
|
||||
small = heap._right;
|
||||
}
|
||||
|
||||
return small;
|
||||
};
|
||||
|
||||
Heap.prototype._largest = function(heap) {
|
||||
var large = heap;
|
||||
|
||||
if (heap._left && heap._key < heap._left._key) {
|
||||
large = heap._left;
|
||||
}
|
||||
|
||||
if (heap._right && large._key < heap._right._key) {
|
||||
large = heap._right;
|
||||
}
|
||||
|
||||
return large;
|
||||
};
|
||||
|
||||
Heap.prototype._up = function(node) {
|
||||
if (!node || !node._parent)
|
||||
return;
|
||||
|
||||
var next = this._comparator(node._parent);
|
||||
|
||||
if (next != node._parent) {
|
||||
this._swap(node._parent, node);
|
||||
this._up(node);
|
||||
}
|
||||
};
|
||||
|
||||
Heap.prototype._down = function(node) {
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
var next = this._comparator(node);
|
||||
if (next != node) {
|
||||
this._swap(node, next);
|
||||
this._down(node);
|
||||
}
|
||||
};
|
||||
|
||||
var util = require('util');
|
||||
|
||||
Heap.prototype.print = function(stream) {
|
||||
stream.write('digraph {\n');
|
||||
Heap._print(this.root, stream);
|
||||
stream.write('}\n');
|
||||
};
|
||||
|
||||
Heap._print = function(heap, stream) {
|
||||
if (!heap) return;
|
||||
|
||||
if (heap._left) {
|
||||
stream.write(util.format('' + heap._key, '->', heap._left._key, '\n'));
|
||||
Heap._print(heap._left, stream);
|
||||
}
|
||||
|
||||
if (heap._right) {
|
||||
stream.write(util.format('' + heap._key, '->', heap._right._key, '\n'));
|
||||
Heap._print(heap._right, stream);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Heap;
|
|
@ -0,0 +1,15 @@
|
|||
var BinaryHeap = require('./binaryheap');
|
||||
var heap = new BinaryHeap();
|
||||
|
||||
var a = [6, 5, 3, 1, 8, 7, 2, 4];
|
||||
|
||||
a.forEach(function (k) {
|
||||
heap.insert({ value: k }, k);
|
||||
});
|
||||
|
||||
heap.print(process.stdout);
|
||||
|
||||
while (heap.length) {
|
||||
console.log('popping', heap.pop().value);
|
||||
heap.print(process.stdout);
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "binaryheap@>= 0.0.3",
|
||||
"scope": null,
|
||||
"escapedName": "binaryheap",
|
||||
"name": "binaryheap",
|
||||
"rawSpec": ">= 0.0.3",
|
||||
"spec": ">=0.0.3",
|
||||
"type": "range"
|
||||
},
|
||||
"/srv/demos/node_modules/native-dns-cache"
|
||||
]
|
||||
],
|
||||
"_from": "binaryheap@>=0.0.3",
|
||||
"_id": "binaryheap@0.0.3",
|
||||
"_inCache": true,
|
||||
"_location": "/binaryheap",
|
||||
"_npmUser": {
|
||||
"name": "tjfontaine",
|
||||
"email": "tjfontaine@gmail.com"
|
||||
},
|
||||
"_npmVersion": "1.2.14",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "binaryheap@>= 0.0.3",
|
||||
"scope": null,
|
||||
"escapedName": "binaryheap",
|
||||
"name": "binaryheap",
|
||||
"rawSpec": ">= 0.0.3",
|
||||
"spec": ">=0.0.3",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/native-dns-cache"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/binaryheap/-/binaryheap-0.0.3.tgz",
|
||||
"_shasum": "0d6136c84e9f1a5a90c0b97178c3e00df59820d6",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "binaryheap@>= 0.0.3",
|
||||
"_where": "/srv/demos/node_modules/native-dns-cache",
|
||||
"author": {
|
||||
"name": "Timothy J Fontaine",
|
||||
"email": "tjfontaine@gmail.com",
|
||||
"url": "http://atxconsulting.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/tjfontaine/node-binaryheap/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "A simple binary heap",
|
||||
"devDependencies": {
|
||||
"tap": ">= 0.4.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "0d6136c84e9f1a5a90c0b97178c3e00df59820d6",
|
||||
"tarball": "https://registry.npmjs.org/binaryheap/-/binaryheap-0.0.3.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
},
|
||||
"homepage": "http://github.com/tjfontaine/node-binaryheap",
|
||||
"keywords": [
|
||||
"balanced",
|
||||
"binary",
|
||||
"heap",
|
||||
"minheap",
|
||||
"maxheap"
|
||||
],
|
||||
"main": "binaryheap.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "tjfontaine",
|
||||
"email": "tjfontaine@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "binaryheap",
|
||||
"optionalDependencies": {},
|
||||
"readme": "BinaryHeap\n==========\n\nBasic binary heap tree using linked lists\n\nUsage\n-----\n\n```javascript\nvar BinaryHeap = require('binaryheap');\nvar heap = new BinaryHeap();\n\nvar a = [6, 5, 3, 1, 8, 7, 2, 4];\n\na.forEach(function (k) {\n heap.insert({ value: k }, k);\n});\n\nheap.print();\n\nwhile (heap.length) {\n console.log('popping', heap.pop().value);\n}\n```\n\nBy default it stores as a max-heap, if you pass truthy to the constructor though\nit will behave as a min-heap.\n\nMethods\n-------\n\n * `insert(obj, key)` -- obj can be any new or existing object, and key is any\nvalue that behaves sanely with `>` or `<`\n * `pop()` -- removes and returns the maximum or minimum object from the root\nof the heap\n * `remove(obj)` -- removes a previously inserted object from the heap\n * `print()` -- mostly for debugging purposes prints a graphviz dot style\ndigraph to confirm ordering\n\nMembers\n-------\n\n * `length` -- number of objects currently in the heap\n",
|
||||
"readmeFilename": "README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/tjfontaine/node-binaryheap.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test"
|
||||
},
|
||||
"version": "0.0.3"
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
var test = require("tap").test;
|
||||
var Heap = require('./binaryheap');
|
||||
|
||||
test("check order", function (t) {
|
||||
var input = [5, 8, 3, 2, 7, 4, 14];
|
||||
var output = [2, 3, 4, 5, 7, 8, 14];
|
||||
|
||||
var heap = new Heap(true);
|
||||
input.forEach(function (i) {
|
||||
heap.insert({key: i}, i);
|
||||
});
|
||||
|
||||
console.log('foo');
|
||||
|
||||
t.equal(heap.length, input.length, "heap size matches input");
|
||||
|
||||
var o = [];
|
||||
|
||||
for (var i = 0; i < input.length; i++)
|
||||
o.push(heap.pop().key)
|
||||
|
||||
t.equal(o.length, output.length, "heap sorted length matches");
|
||||
t.equivalent(o, output, "heap sorted matches expected output");
|
||||
|
||||
heap = new Heap(false);
|
||||
output.reverse();
|
||||
|
||||
input.forEach(function (i) {
|
||||
heap.insert({key: i}, i);
|
||||
});
|
||||
|
||||
t.equal(heap.length, input.length, "heap size matches input");
|
||||
|
||||
var o = [];
|
||||
|
||||
for (var i = 0; i < input.length; i++)
|
||||
o.push(heap.pop().key)
|
||||
|
||||
t.equal(o.length, output.length, "heap sorted length matches");
|
||||
t.equivalent(o, output, "heap sorted matches expected output");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
var tree_count = 9;
|
||||
|
||||
function getDot() {
|
||||
var tree = require('fs').createWriteStream('tree.'+ ++tree_count + '.dot');
|
||||
return tree;
|
||||
};
|
||||
|
||||
function printHeap(heap) {
|
||||
//rm -f *.dot *.gif && node test && for i in $(ls tree.*.dot); do dot -Tgif $i -o $(basename $i .dot).gif; done && gifsicle --delay=100 --loop *.gif > anim.gif
|
||||
//var ds = getDot();
|
||||
//heap.print(ds);
|
||||
//ds.end();
|
||||
};
|
||||
|
||||
|
||||
test("remove arbitrary elements", function (t) {
|
||||
var heap = new Heap();
|
||||
|
||||
var elems = {
|
||||
a: { key: 5 },
|
||||
b: { key: 7 },
|
||||
c: { key: 3 },
|
||||
d: { key: 14 },
|
||||
e: { key: 8 },
|
||||
f: { key: 30 },
|
||||
g: { key: 23 },
|
||||
h: { key: 1 },
|
||||
};
|
||||
|
||||
Object.keys(elems).forEach(function (key) {
|
||||
heap.insert(elems[key], elems[key].key);
|
||||
printHeap(heap);
|
||||
});
|
||||
|
||||
heap.remove(elems.e);
|
||||
printHeap(heap);
|
||||
|
||||
t.equal(heap.length, heap.count(heap.root), "length and count should match");
|
||||
t.equal(heap.length, Object.keys(elems).length - 1, "should only remove one ndoe");
|
||||
printHeap(heap);
|
||||
|
||||
heap.remove(elems.a);
|
||||
t.equal(heap.length, heap.count(heap.root), "length and count should match");
|
||||
printHeap(heap);
|
||||
|
||||
|
||||
heap.remove(elems.b);
|
||||
t.equal(heap.length, heap.count(heap.root), "length and count should match");
|
||||
printHeap(heap);
|
||||
|
||||
t.end();
|
||||
});
|
|
@ -0,0 +1,47 @@
|
|||
BufferCursor
|
||||
============
|
||||
|
||||
This is a simple module that allows you to traverse a Buffer iteratively. You
|
||||
can read and write different types and the cursor's position will update with
|
||||
the proper size, which you can see through `.tell()` you can also
|
||||
`.seek()`
|
||||
|
||||
```javascript
|
||||
var bc = new BufferCursor(buffer);
|
||||
bc.readUInt16BE();
|
||||
bc.readUInt8();
|
||||
bc.readUInt32BE();
|
||||
console.log(bc.tell());
|
||||
```
|
||||
|
||||
Will output `7`
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
For the most part `BufferCursor` and `Buffer` share the same methods, there's
|
||||
just a slight alteration in method signature, none of the methods take an
|
||||
offset.
|
||||
|
||||
So `.readUInt16LE(10)` in `Buffer` is equivalent to `bs.seek(10); bs.readUInt16LE();`
|
||||
|
||||
All `read[U]Int` and `write[U]Int` methods are reproduced, as are `toString`,
|
||||
`write`, `fill`, and `slice`. All of these methods will move the cursor through
|
||||
the stream and do not take an offset parameter, where an `end` parameter would
|
||||
normaly be used, here you supply a `length`.
|
||||
|
||||
The following are additional methods:
|
||||
|
||||
* `seek(value)` -- Seek to an arbitrary position in the stream
|
||||
* `tell()` -- Return the current location in the stream
|
||||
* `eof()` -- Return true if at the end of the stream
|
||||
* `toByteArray([method])` -- This is a special helper method which will return
|
||||
the *entire* stream (i.e. from the start) as an array of numbers.
|
||||
- By default it will use `readUInt8` but you can pass in any
|
||||
`read[U]Int[8,16,32][LE,BE]` to change what the array is made of
|
||||
|
||||
Properties
|
||||
----------
|
||||
|
||||
* `.buffer` -- Access to the raw buffer
|
||||
* `.length` -- The size of the buffer
|
|
@ -0,0 +1,388 @@
|
|||
// Copyright 2012 Timothy J Fontaine <tjfontaine@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE
|
||||
|
||||
var util = require('util');
|
||||
var VError = require('verror');
|
||||
|
||||
var BufferCursor = module.exports = function(buff, noAssert) {
|
||||
if (!(this instanceof BufferCursor))
|
||||
return new BufferCursor(buff, noAssert);
|
||||
|
||||
this._pos = 0;
|
||||
|
||||
this._noAssert = noAssert;
|
||||
|
||||
if (this._noAssert === undefined)
|
||||
this._noAssert = true;
|
||||
|
||||
this.buffer = buff;
|
||||
this.length = buff.length;
|
||||
};
|
||||
|
||||
var BCO = BufferCursor.BufferCursorOverflow = function(length, pos, size) {
|
||||
this.kind = 'BufferCursorOverflow';
|
||||
this.length = length;
|
||||
this.position = pos;
|
||||
this.size = size;
|
||||
VError.call(this,
|
||||
'BufferCursorOverflow: length %d, position %d, size %d',
|
||||
length,
|
||||
pos,
|
||||
size);
|
||||
};
|
||||
util.inherits(BCO, VError);
|
||||
|
||||
BufferCursor.prototype._move = function(step) {
|
||||
this._checkWrite(step);
|
||||
this._pos += step;
|
||||
};
|
||||
|
||||
BufferCursor.prototype._checkWrite = function(size) {
|
||||
var shouldThrow = false;
|
||||
|
||||
var length = this.length;
|
||||
var pos = this._pos;
|
||||
|
||||
if (size > length)
|
||||
shouldThrow = true;
|
||||
|
||||
if (length - pos < size)
|
||||
shouldThrow = true;
|
||||
|
||||
if (shouldThrow) {
|
||||
var bco = new BCO(length,
|
||||
pos,
|
||||
size);
|
||||
throw bco;
|
||||
}
|
||||
}
|
||||
|
||||
BufferCursor.prototype.seek = function(pos) {
|
||||
if (pos < 0)
|
||||
throw new VError(new RangeError('Cannot seek before start of buffer'),
|
||||
'Negative seek values not allowed: %d', pos);
|
||||
|
||||
if (pos > this.length)
|
||||
throw new VError(new RangeError('Trying to seek beyond buffer'),
|
||||
'Requested %d position is beyond length %d',
|
||||
pos, this.length);
|
||||
|
||||
this._pos = pos;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.eof = function() {
|
||||
return this._pos == this.length;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.toByteArray = function(method) {
|
||||
var arr = [], i, part, count;
|
||||
|
||||
if (!method) {
|
||||
method = 'readUInt8';
|
||||
part = 1;
|
||||
}
|
||||
|
||||
if (method.indexOf('16') > 0)
|
||||
part = 2;
|
||||
else if (method.indexOf('32') > 0)
|
||||
part = 4;
|
||||
|
||||
count = this.length / part;
|
||||
|
||||
for (i = 0; i < this.buffer.length; i += part) {
|
||||
arr.push(this.buffer[method](i));
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.tell = function() {
|
||||
return this._pos;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.slice = function(length) {
|
||||
var end, b;
|
||||
|
||||
if (length === undefined) {
|
||||
end = this.length;
|
||||
} else {
|
||||
end = this._pos + length;
|
||||
}
|
||||
|
||||
b = new BufferCursor(this.buffer.slice(this._pos, end));
|
||||
this.seek(end);
|
||||
|
||||
return b;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.toString = function(encoding, length) {
|
||||
var end, ret;
|
||||
|
||||
if (length === undefined) {
|
||||
end = this.length;
|
||||
} else {
|
||||
end = this._pos + length;
|
||||
}
|
||||
|
||||
if (!encoding) {
|
||||
encoding = 'utf8';
|
||||
}
|
||||
|
||||
ret = this.buffer.toString(encoding, this._pos, end);
|
||||
this.seek(end);
|
||||
return ret;
|
||||
};
|
||||
|
||||
// This method doesn't need to _checkWrite because Buffer implicitly truncates
|
||||
// to the length of the buffer, it's the only method in Node core that behaves
|
||||
// this way by default
|
||||
BufferCursor.prototype.write = function(value, length, encoding) {
|
||||
var end, ret;
|
||||
|
||||
ret = this.buffer.write(value, this._pos, length, encoding);
|
||||
this._move(ret);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.fill = function(value, length) {
|
||||
var end;
|
||||
|
||||
if (length === undefined) {
|
||||
end = this.length;
|
||||
} else {
|
||||
end = this._pos + length;
|
||||
}
|
||||
|
||||
this._checkWrite(end - this._pos);
|
||||
|
||||
this.buffer.fill(value, this._pos, end);
|
||||
this.seek(end);
|
||||
return this;
|
||||
};
|
||||
|
||||
// This prototype is not entirely like the upstream Buffer.copy, instead it
|
||||
// is the target buffer, and accepts the source buffer -- since the target
|
||||
// buffer knows its starting position
|
||||
BufferCursor.prototype.copy = function copy(source, sourceStart, sourceEnd) {
|
||||
var sBC = source instanceof BufferCursor;
|
||||
|
||||
if (isNaN(sourceEnd))
|
||||
sourceEnd = source.length;
|
||||
|
||||
if (isNaN(sourceStart)) {
|
||||
if (sBC)
|
||||
sourceStart = source._pos;
|
||||
else
|
||||
sourceStart = 0;
|
||||
}
|
||||
|
||||
var length = sourceEnd - sourceStart;
|
||||
|
||||
this._checkWrite(length);
|
||||
|
||||
var buf = sBC ? source.buffer : source;
|
||||
|
||||
buf.copy(this.buffer, this._pos, sourceStart, sourceEnd);
|
||||
|
||||
this._move(length);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readUInt8 = function() {
|
||||
var ret = this.buffer.readUInt8(this._pos, this._noAssert);
|
||||
this._move(1);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readInt8 = function() {
|
||||
var ret = this.buffer.readInt8(this._pos, this._noAssert);
|
||||
this._move(1);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readInt16BE = function() {
|
||||
var ret = this.buffer.readInt16BE(this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readInt16LE = function() {
|
||||
var ret = this.buffer.readInt16LE(this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readUInt16BE = function() {
|
||||
var ret = this.buffer.readUInt16BE(this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readUInt16LE = function() {
|
||||
var ret = this.buffer.readUInt16LE(this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readUInt32LE = function() {
|
||||
var ret = this.buffer.readUInt32LE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readUInt32BE = function() {
|
||||
var ret = this.buffer.readUInt32BE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readInt32LE = function() {
|
||||
var ret = this.buffer.readInt32LE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readInt32BE = function() {
|
||||
var ret = this.buffer.readInt32BE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readFloatBE = function() {
|
||||
var ret = this.buffer.readFloatBE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readFloatLE = function() {
|
||||
var ret = this.buffer.readFloatLE(this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readDoubleBE = function() {
|
||||
var ret = this.buffer.readDoubleBE(this._pos, this._noAssert);
|
||||
this._move(8);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.readDoubleLE = function() {
|
||||
var ret = this.buffer.readDoubleLE(this._pos, this._noAssert);
|
||||
this._move(8);
|
||||
return ret;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeUInt8 = function(value) {
|
||||
this._checkWrite(1);
|
||||
this.buffer.writeUInt8(value, this._pos, this._noAssert);
|
||||
this._move(1);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeInt8 = function(value) {
|
||||
this._checkWrite(1);
|
||||
this.buffer.writeInt8(value, this._pos, this._noAssert);
|
||||
this._move(1);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeUInt16BE = function(value) {
|
||||
this._checkWrite(2);
|
||||
this.buffer.writeUInt16BE(value, this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeUInt16LE = function(value) {
|
||||
this._checkWrite(2);
|
||||
this.buffer.writeUInt16LE(value, this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeInt16BE = function(value) {
|
||||
this._checkWrite(2);
|
||||
this.buffer.writeInt16BE(value, this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeInt16LE = function(value) {
|
||||
this._checkWrite(2);
|
||||
this.buffer.writeInt16LE(value, this._pos, this._noAssert);
|
||||
this._move(2);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeUInt32BE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeUInt32BE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeUInt32LE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeUInt32LE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeInt32BE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeInt32BE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeInt32LE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeInt32LE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeFloatBE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeFloatBE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeFloatLE = function(value) {
|
||||
this._checkWrite(4);
|
||||
this.buffer.writeFloatLE(value, this._pos, this._noAssert);
|
||||
this._move(4);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeDoubleBE = function(value) {
|
||||
this._checkWrite(8);
|
||||
this.buffer.writeDoubleBE(value, this._pos, this._noAssert);
|
||||
this._move(8);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferCursor.prototype.writeDoubleLE = function(value) {
|
||||
this._checkWrite(8);
|
||||
this.buffer.writeDoubleLE(value, this._pos, this._noAssert);
|
||||
this._move(8);
|
||||
return this;
|
||||
};
|
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "buffercursor@>= 0.0.12",
|
||||
"scope": null,
|
||||
"escapedName": "buffercursor",
|
||||
"name": "buffercursor",
|
||||
"rawSpec": ">= 0.0.12",
|
||||
"spec": ">=0.0.12",
|
||||
"type": "range"
|
||||
},
|
||||
"/srv/demos/node_modules/native-dns-packet"
|
||||
]
|
||||
],
|
||||
"_from": "buffercursor@>=0.0.12",
|
||||
"_id": "buffercursor@0.0.12",
|
||||
"_inCache": true,
|
||||
"_location": "/buffercursor",
|
||||
"_npmUser": {
|
||||
"name": "tjfontaine",
|
||||
"email": "tjfontaine@gmail.com"
|
||||
},
|
||||
"_npmVersion": "1.4.3",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "buffercursor@>= 0.0.12",
|
||||
"scope": null,
|
||||
"escapedName": "buffercursor",
|
||||
"name": "buffercursor",
|
||||
"rawSpec": ">= 0.0.12",
|
||||
"spec": ">=0.0.12",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/native-dns-packet"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/buffercursor/-/buffercursor-0.0.12.tgz",
|
||||
"_shasum": "78a9a7f4343ae7d820a8999acc80de591e25a779",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "buffercursor@>= 0.0.12",
|
||||
"_where": "/srv/demos/node_modules/native-dns-packet",
|
||||
"author": {
|
||||
"name": "Timothy J Fontaine",
|
||||
"email": "tjfontaine@gmail.com",
|
||||
"url": "http://atxconsulting.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "http://github.com/tjfontaine/node-buffercursor/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"verror": "^1.4.0"
|
||||
},
|
||||
"description": "A simple way to traverse a Buffer like a cursor, updating position along the way",
|
||||
"devDependencies": {},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "78a9a7f4343ae7d820a8999acc80de591e25a779",
|
||||
"tarball": "https://registry.npmjs.org/buffercursor/-/buffercursor-0.0.12.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.5.0"
|
||||
},
|
||||
"homepage": "http://github.com/tjfontaine/node-buffercursor",
|
||||
"keywords": [
|
||||
"buffer",
|
||||
"cursor",
|
||||
"stream"
|
||||
],
|
||||
"main": "buffercursor.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "tjfontaine",
|
||||
"email": "tjfontaine@gmail.com"
|
||||
}
|
||||
],
|
||||
"name": "buffercursor",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/tjfontaine/node-buffercursor.git"
|
||||
},
|
||||
"version": "0.0.12"
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
|
@ -0,0 +1,3 @@
|
|||
# core-util-is
|
||||
|
||||
The `util.is*` functions introduced in Node v0.12.
|
|
@ -0,0 +1,604 @@
|
|||
diff --git a/lib/util.js b/lib/util.js
|
||||
index a03e874..9074e8e 100644
|
||||
--- a/lib/util.js
|
||||
+++ b/lib/util.js
|
||||
@@ -19,430 +19,6 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-var formatRegExp = /%[sdj%]/g;
|
||||
-exports.format = function(f) {
|
||||
- if (!isString(f)) {
|
||||
- var objects = [];
|
||||
- for (var i = 0; i < arguments.length; i++) {
|
||||
- objects.push(inspect(arguments[i]));
|
||||
- }
|
||||
- return objects.join(' ');
|
||||
- }
|
||||
-
|
||||
- var i = 1;
|
||||
- var args = arguments;
|
||||
- var len = args.length;
|
||||
- var str = String(f).replace(formatRegExp, function(x) {
|
||||
- if (x === '%%') return '%';
|
||||
- if (i >= len) return x;
|
||||
- switch (x) {
|
||||
- case '%s': return String(args[i++]);
|
||||
- case '%d': return Number(args[i++]);
|
||||
- case '%j':
|
||||
- try {
|
||||
- return JSON.stringify(args[i++]);
|
||||
- } catch (_) {
|
||||
- return '[Circular]';
|
||||
- }
|
||||
- default:
|
||||
- return x;
|
||||
- }
|
||||
- });
|
||||
- for (var x = args[i]; i < len; x = args[++i]) {
|
||||
- if (isNull(x) || !isObject(x)) {
|
||||
- str += ' ' + x;
|
||||
- } else {
|
||||
- str += ' ' + inspect(x);
|
||||
- }
|
||||
- }
|
||||
- return str;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-// Mark that a method should not be used.
|
||||
-// Returns a modified function which warns once by default.
|
||||
-// If --no-deprecation is set, then it is a no-op.
|
||||
-exports.deprecate = function(fn, msg) {
|
||||
- // Allow for deprecating things in the process of starting up.
|
||||
- if (isUndefined(global.process)) {
|
||||
- return function() {
|
||||
- return exports.deprecate(fn, msg).apply(this, arguments);
|
||||
- };
|
||||
- }
|
||||
-
|
||||
- if (process.noDeprecation === true) {
|
||||
- return fn;
|
||||
- }
|
||||
-
|
||||
- var warned = false;
|
||||
- function deprecated() {
|
||||
- if (!warned) {
|
||||
- if (process.throwDeprecation) {
|
||||
- throw new Error(msg);
|
||||
- } else if (process.traceDeprecation) {
|
||||
- console.trace(msg);
|
||||
- } else {
|
||||
- console.error(msg);
|
||||
- }
|
||||
- warned = true;
|
||||
- }
|
||||
- return fn.apply(this, arguments);
|
||||
- }
|
||||
-
|
||||
- return deprecated;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-var debugs = {};
|
||||
-var debugEnviron;
|
||||
-exports.debuglog = function(set) {
|
||||
- if (isUndefined(debugEnviron))
|
||||
- debugEnviron = process.env.NODE_DEBUG || '';
|
||||
- set = set.toUpperCase();
|
||||
- if (!debugs[set]) {
|
||||
- if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
||||
- var pid = process.pid;
|
||||
- debugs[set] = function() {
|
||||
- var msg = exports.format.apply(exports, arguments);
|
||||
- console.error('%s %d: %s', set, pid, msg);
|
||||
- };
|
||||
- } else {
|
||||
- debugs[set] = function() {};
|
||||
- }
|
||||
- }
|
||||
- return debugs[set];
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Echos the value of a value. Trys to print the value out
|
||||
- * in the best way possible given the different types.
|
||||
- *
|
||||
- * @param {Object} obj The object to print out.
|
||||
- * @param {Object} opts Optional options object that alters the output.
|
||||
- */
|
||||
-/* legacy: obj, showHidden, depth, colors*/
|
||||
-function inspect(obj, opts) {
|
||||
- // default options
|
||||
- var ctx = {
|
||||
- seen: [],
|
||||
- stylize: stylizeNoColor
|
||||
- };
|
||||
- // legacy...
|
||||
- if (arguments.length >= 3) ctx.depth = arguments[2];
|
||||
- if (arguments.length >= 4) ctx.colors = arguments[3];
|
||||
- if (isBoolean(opts)) {
|
||||
- // legacy...
|
||||
- ctx.showHidden = opts;
|
||||
- } else if (opts) {
|
||||
- // got an "options" object
|
||||
- exports._extend(ctx, opts);
|
||||
- }
|
||||
- // set default options
|
||||
- if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
||||
- if (isUndefined(ctx.depth)) ctx.depth = 2;
|
||||
- if (isUndefined(ctx.colors)) ctx.colors = false;
|
||||
- if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
||||
- if (ctx.colors) ctx.stylize = stylizeWithColor;
|
||||
- return formatValue(ctx, obj, ctx.depth);
|
||||
-}
|
||||
-exports.inspect = inspect;
|
||||
-
|
||||
-
|
||||
-// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||||
-inspect.colors = {
|
||||
- 'bold' : [1, 22],
|
||||
- 'italic' : [3, 23],
|
||||
- 'underline' : [4, 24],
|
||||
- 'inverse' : [7, 27],
|
||||
- 'white' : [37, 39],
|
||||
- 'grey' : [90, 39],
|
||||
- 'black' : [30, 39],
|
||||
- 'blue' : [34, 39],
|
||||
- 'cyan' : [36, 39],
|
||||
- 'green' : [32, 39],
|
||||
- 'magenta' : [35, 39],
|
||||
- 'red' : [31, 39],
|
||||
- 'yellow' : [33, 39]
|
||||
-};
|
||||
-
|
||||
-// Don't use 'blue' not visible on cmd.exe
|
||||
-inspect.styles = {
|
||||
- 'special': 'cyan',
|
||||
- 'number': 'yellow',
|
||||
- 'boolean': 'yellow',
|
||||
- 'undefined': 'grey',
|
||||
- 'null': 'bold',
|
||||
- 'string': 'green',
|
||||
- 'date': 'magenta',
|
||||
- // "name": intentionally not styling
|
||||
- 'regexp': 'red'
|
||||
-};
|
||||
-
|
||||
-
|
||||
-function stylizeWithColor(str, styleType) {
|
||||
- var style = inspect.styles[styleType];
|
||||
-
|
||||
- if (style) {
|
||||
- return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
||||
- '\u001b[' + inspect.colors[style][1] + 'm';
|
||||
- } else {
|
||||
- return str;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function stylizeNoColor(str, styleType) {
|
||||
- return str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function arrayToHash(array) {
|
||||
- var hash = {};
|
||||
-
|
||||
- array.forEach(function(val, idx) {
|
||||
- hash[val] = true;
|
||||
- });
|
||||
-
|
||||
- return hash;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatValue(ctx, value, recurseTimes) {
|
||||
- // Provide a hook for user-specified inspect functions.
|
||||
- // Check that value is an object with an inspect function on it
|
||||
- if (ctx.customInspect &&
|
||||
- value &&
|
||||
- isFunction(value.inspect) &&
|
||||
- // Filter out the util module, it's inspect function is special
|
||||
- value.inspect !== exports.inspect &&
|
||||
- // Also filter out any prototype objects using the circular check.
|
||||
- !(value.constructor && value.constructor.prototype === value)) {
|
||||
- var ret = value.inspect(recurseTimes, ctx);
|
||||
- if (!isString(ret)) {
|
||||
- ret = formatValue(ctx, ret, recurseTimes);
|
||||
- }
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- // Primitive types cannot have properties
|
||||
- var primitive = formatPrimitive(ctx, value);
|
||||
- if (primitive) {
|
||||
- return primitive;
|
||||
- }
|
||||
-
|
||||
- // Look up the keys of the object.
|
||||
- var keys = Object.keys(value);
|
||||
- var visibleKeys = arrayToHash(keys);
|
||||
-
|
||||
- if (ctx.showHidden) {
|
||||
- keys = Object.getOwnPropertyNames(value);
|
||||
- }
|
||||
-
|
||||
- // Some type of object without properties can be shortcutted.
|
||||
- if (keys.length === 0) {
|
||||
- if (isFunction(value)) {
|
||||
- var name = value.name ? ': ' + value.name : '';
|
||||
- return ctx.stylize('[Function' + name + ']', 'special');
|
||||
- }
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- }
|
||||
- if (isDate(value)) {
|
||||
- return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
||||
- }
|
||||
- if (isError(value)) {
|
||||
- return formatError(value);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- var base = '', array = false, braces = ['{', '}'];
|
||||
-
|
||||
- // Make Array say that they are Array
|
||||
- if (isArray(value)) {
|
||||
- array = true;
|
||||
- braces = ['[', ']'];
|
||||
- }
|
||||
-
|
||||
- // Make functions say that they are functions
|
||||
- if (isFunction(value)) {
|
||||
- var n = value.name ? ': ' + value.name : '';
|
||||
- base = ' [Function' + n + ']';
|
||||
- }
|
||||
-
|
||||
- // Make RegExps say that they are RegExps
|
||||
- if (isRegExp(value)) {
|
||||
- base = ' ' + RegExp.prototype.toString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make dates with properties first say the date
|
||||
- if (isDate(value)) {
|
||||
- base = ' ' + Date.prototype.toUTCString.call(value);
|
||||
- }
|
||||
-
|
||||
- // Make error with message first say the error
|
||||
- if (isError(value)) {
|
||||
- base = ' ' + formatError(value);
|
||||
- }
|
||||
-
|
||||
- if (keys.length === 0 && (!array || value.length == 0)) {
|
||||
- return braces[0] + base + braces[1];
|
||||
- }
|
||||
-
|
||||
- if (recurseTimes < 0) {
|
||||
- if (isRegExp(value)) {
|
||||
- return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||||
- } else {
|
||||
- return ctx.stylize('[Object]', 'special');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- ctx.seen.push(value);
|
||||
-
|
||||
- var output;
|
||||
- if (array) {
|
||||
- output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||||
- } else {
|
||||
- output = keys.map(function(key) {
|
||||
- return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- ctx.seen.pop();
|
||||
-
|
||||
- return reduceToSingleString(output, base, braces);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatPrimitive(ctx, value) {
|
||||
- if (isUndefined(value))
|
||||
- return ctx.stylize('undefined', 'undefined');
|
||||
- if (isString(value)) {
|
||||
- var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||||
- .replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"') + '\'';
|
||||
- return ctx.stylize(simple, 'string');
|
||||
- }
|
||||
- if (isNumber(value)) {
|
||||
- // Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
|
||||
- // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
|
||||
- if (value === 0 && 1 / value < 0)
|
||||
- return ctx.stylize('-0', 'number');
|
||||
- return ctx.stylize('' + value, 'number');
|
||||
- }
|
||||
- if (isBoolean(value))
|
||||
- return ctx.stylize('' + value, 'boolean');
|
||||
- // For some reason typeof null is "object", so special case here.
|
||||
- if (isNull(value))
|
||||
- return ctx.stylize('null', 'null');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatError(value) {
|
||||
- return '[' + Error.prototype.toString.call(value) + ']';
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||||
- var output = [];
|
||||
- for (var i = 0, l = value.length; i < l; ++i) {
|
||||
- if (hasOwnProperty(value, String(i))) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- String(i), true));
|
||||
- } else {
|
||||
- output.push('');
|
||||
- }
|
||||
- }
|
||||
- keys.forEach(function(key) {
|
||||
- if (!key.match(/^\d+$/)) {
|
||||
- output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||||
- key, true));
|
||||
- }
|
||||
- });
|
||||
- return output;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||||
- var name, str, desc;
|
||||
- desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
||||
- if (desc.get) {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Getter/Setter]', 'special');
|
||||
- } else {
|
||||
- str = ctx.stylize('[Getter]', 'special');
|
||||
- }
|
||||
- } else {
|
||||
- if (desc.set) {
|
||||
- str = ctx.stylize('[Setter]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (!hasOwnProperty(visibleKeys, key)) {
|
||||
- name = '[' + key + ']';
|
||||
- }
|
||||
- if (!str) {
|
||||
- if (ctx.seen.indexOf(desc.value) < 0) {
|
||||
- if (isNull(recurseTimes)) {
|
||||
- str = formatValue(ctx, desc.value, null);
|
||||
- } else {
|
||||
- str = formatValue(ctx, desc.value, recurseTimes - 1);
|
||||
- }
|
||||
- if (str.indexOf('\n') > -1) {
|
||||
- if (array) {
|
||||
- str = str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n').substr(2);
|
||||
- } else {
|
||||
- str = '\n' + str.split('\n').map(function(line) {
|
||||
- return ' ' + line;
|
||||
- }).join('\n');
|
||||
- }
|
||||
- }
|
||||
- } else {
|
||||
- str = ctx.stylize('[Circular]', 'special');
|
||||
- }
|
||||
- }
|
||||
- if (isUndefined(name)) {
|
||||
- if (array && key.match(/^\d+$/)) {
|
||||
- return str;
|
||||
- }
|
||||
- name = JSON.stringify('' + key);
|
||||
- if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||||
- name = name.substr(1, name.length - 2);
|
||||
- name = ctx.stylize(name, 'name');
|
||||
- } else {
|
||||
- name = name.replace(/'/g, "\\'")
|
||||
- .replace(/\\"/g, '"')
|
||||
- .replace(/(^"|"$)/g, "'");
|
||||
- name = ctx.stylize(name, 'string');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return name + ': ' + str;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function reduceToSingleString(output, base, braces) {
|
||||
- var numLinesEst = 0;
|
||||
- var length = output.reduce(function(prev, cur) {
|
||||
- numLinesEst++;
|
||||
- if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||||
- return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
||||
- }, 0);
|
||||
-
|
||||
- if (length > 60) {
|
||||
- return braces[0] +
|
||||
- (base === '' ? '' : base + '\n ') +
|
||||
- ' ' +
|
||||
- output.join(',\n ') +
|
||||
- ' ' +
|
||||
- braces[1];
|
||||
- }
|
||||
-
|
||||
- return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||||
-}
|
||||
-
|
||||
-
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
function isArray(ar) {
|
||||
@@ -522,166 +98,10 @@ function isPrimitive(arg) {
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
function isBuffer(arg) {
|
||||
- return arg instanceof Buffer;
|
||||
+ return Buffer.isBuffer(arg);
|
||||
}
|
||||
exports.isBuffer = isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-function pad(n) {
|
||||
- return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||||
- 'Oct', 'Nov', 'Dec'];
|
||||
-
|
||||
-// 26 Feb 16:19:34
|
||||
-function timestamp() {
|
||||
- var d = new Date();
|
||||
- var time = [pad(d.getHours()),
|
||||
- pad(d.getMinutes()),
|
||||
- pad(d.getSeconds())].join(':');
|
||||
- return [d.getDate(), months[d.getMonth()], time].join(' ');
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// log is just a thin wrapper to console.log that prepends a timestamp
|
||||
-exports.log = function() {
|
||||
- console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Inherit the prototype methods from one constructor into another.
|
||||
- *
|
||||
- * The Function.prototype.inherits from lang.js rewritten as a standalone
|
||||
- * function (not on Function.prototype). NOTE: If this file is to be loaded
|
||||
- * during bootstrapping this function needs to be rewritten using some native
|
||||
- * functions as prototype setup using normal JavaScript does not work as
|
||||
- * expected during bootstrapping (see mirror.js in r114903).
|
||||
- *
|
||||
- * @param {function} ctor Constructor function which needs to inherit the
|
||||
- * prototype.
|
||||
- * @param {function} superCtor Constructor function to inherit prototype from.
|
||||
- */
|
||||
-exports.inherits = function(ctor, superCtor) {
|
||||
- ctor.super_ = superCtor;
|
||||
- ctor.prototype = Object.create(superCtor.prototype, {
|
||||
- constructor: {
|
||||
- value: ctor,
|
||||
- enumerable: false,
|
||||
- writable: true,
|
||||
- configurable: true
|
||||
- }
|
||||
- });
|
||||
-};
|
||||
-
|
||||
-exports._extend = function(origin, add) {
|
||||
- // Don't do anything if add isn't an object
|
||||
- if (!add || !isObject(add)) return origin;
|
||||
-
|
||||
- var keys = Object.keys(add);
|
||||
- var i = keys.length;
|
||||
- while (i--) {
|
||||
- origin[keys[i]] = add[keys[i]];
|
||||
- }
|
||||
- return origin;
|
||||
-};
|
||||
-
|
||||
-function hasOwnProperty(obj, prop) {
|
||||
- return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-// Deprecated old stuff.
|
||||
-
|
||||
-exports.p = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- console.error(exports.inspect(arguments[i]));
|
||||
- }
|
||||
-}, 'util.p: Use console.error() instead');
|
||||
-
|
||||
-
|
||||
-exports.exec = exports.deprecate(function() {
|
||||
- return require('child_process').exec.apply(this, arguments);
|
||||
-}, 'util.exec is now called `child_process.exec`.');
|
||||
-
|
||||
-
|
||||
-exports.print = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(String(arguments[i]));
|
||||
- }
|
||||
-}, 'util.print: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.puts = exports.deprecate(function() {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stdout.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.puts: Use console.log instead');
|
||||
-
|
||||
-
|
||||
-exports.debug = exports.deprecate(function(x) {
|
||||
- process.stderr.write('DEBUG: ' + x + '\n');
|
||||
-}, 'util.debug: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.error = exports.deprecate(function(x) {
|
||||
- for (var i = 0, len = arguments.length; i < len; ++i) {
|
||||
- process.stderr.write(arguments[i] + '\n');
|
||||
- }
|
||||
-}, 'util.error: Use console.error instead');
|
||||
-
|
||||
-
|
||||
-exports.pump = exports.deprecate(function(readStream, writeStream, callback) {
|
||||
- var callbackCalled = false;
|
||||
-
|
||||
- function call(a, b, c) {
|
||||
- if (callback && !callbackCalled) {
|
||||
- callback(a, b, c);
|
||||
- callbackCalled = true;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- readStream.addListener('data', function(chunk) {
|
||||
- if (writeStream.write(chunk) === false) readStream.pause();
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('drain', function() {
|
||||
- readStream.resume();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('end', function() {
|
||||
- writeStream.end();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('close', function() {
|
||||
- call();
|
||||
- });
|
||||
-
|
||||
- readStream.addListener('error', function(err) {
|
||||
- writeStream.end();
|
||||
- call(err);
|
||||
- });
|
||||
-
|
||||
- writeStream.addListener('error', function(err) {
|
||||
- readStream.destroy();
|
||||
- call(err);
|
||||
- });
|
||||
-}, 'util.pump(): Use readableStream.pipe() instead');
|
||||
-
|
||||
-
|
||||
-var uv;
|
||||
-exports._errnoException = function(err, syscall) {
|
||||
- if (isUndefined(uv)) uv = process.binding('uv');
|
||||
- var errname = uv.errname(err);
|
||||
- var e = new Error(syscall + ' ' + errname);
|
||||
- e.code = errname;
|
||||
- e.errno = errname;
|
||||
- e.syscall = syscall;
|
||||
- return e;
|
||||
-};
|
||||
+}
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
|
||||
function isArray(arg) {
|
||||
if (Array.isArray) {
|
||||
return Array.isArray(arg);
|
||||
}
|
||||
return objectToString(arg) === '[object Array]';
|
||||
}
|
||||
exports.isArray = isArray;
|
||||
|
||||
function isBoolean(arg) {
|
||||
return typeof arg === 'boolean';
|
||||
}
|
||||
exports.isBoolean = isBoolean;
|
||||
|
||||
function isNull(arg) {
|
||||
return arg === null;
|
||||
}
|
||||
exports.isNull = isNull;
|
||||
|
||||
function isNullOrUndefined(arg) {
|
||||
return arg == null;
|
||||
}
|
||||
exports.isNullOrUndefined = isNullOrUndefined;
|
||||
|
||||
function isNumber(arg) {
|
||||
return typeof arg === 'number';
|
||||
}
|
||||
exports.isNumber = isNumber;
|
||||
|
||||
function isString(arg) {
|
||||
return typeof arg === 'string';
|
||||
}
|
||||
exports.isString = isString;
|
||||
|
||||
function isSymbol(arg) {
|
||||
return typeof arg === 'symbol';
|
||||
}
|
||||
exports.isSymbol = isSymbol;
|
||||
|
||||
function isUndefined(arg) {
|
||||
return arg === void 0;
|
||||
}
|
||||
exports.isUndefined = isUndefined;
|
||||
|
||||
function isRegExp(re) {
|
||||
return objectToString(re) === '[object RegExp]';
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
function isObject(arg) {
|
||||
return typeof arg === 'object' && arg !== null;
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
|
||||
function isDate(d) {
|
||||
return objectToString(d) === '[object Date]';
|
||||
}
|
||||
exports.isDate = isDate;
|
||||
|
||||
function isError(e) {
|
||||
return (objectToString(e) === '[object Error]' || e instanceof Error);
|
||||
}
|
||||
exports.isError = isError;
|
||||
|
||||
function isFunction(arg) {
|
||||
return typeof arg === 'function';
|
||||
}
|
||||
exports.isFunction = isFunction;
|
||||
|
||||
function isPrimitive(arg) {
|
||||
return arg === null ||
|
||||
typeof arg === 'boolean' ||
|
||||
typeof arg === 'number' ||
|
||||
typeof arg === 'string' ||
|
||||
typeof arg === 'symbol' || // ES6 symbol
|
||||
typeof arg === 'undefined';
|
||||
}
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
exports.isBuffer = Buffer.isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "core-util-is@1.0.2",
|
||||
"scope": null,
|
||||
"escapedName": "core-util-is",
|
||||
"name": "core-util-is",
|
||||
"rawSpec": "1.0.2",
|
||||
"spec": "1.0.2",
|
||||
"type": "version"
|
||||
},
|
||||
"/srv/demos/node_modules/verror"
|
||||
]
|
||||
],
|
||||
"_from": "core-util-is@1.0.2",
|
||||
"_id": "core-util-is@1.0.2",
|
||||
"_inCache": true,
|
||||
"_location": "/core-util-is",
|
||||
"_nodeVersion": "4.0.0",
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
},
|
||||
"_npmVersion": "3.3.2",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "core-util-is@1.0.2",
|
||||
"scope": null,
|
||||
"escapedName": "core-util-is",
|
||||
"name": "core-util-is",
|
||||
"rawSpec": "1.0.2",
|
||||
"spec": "1.0.2",
|
||||
"type": "version"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/verror"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "core-util-is@1.0.2",
|
||||
"_where": "/srv/demos/node_modules/verror",
|
||||
"author": {
|
||||
"name": "Isaac Z. Schlueter",
|
||||
"email": "i@izs.me",
|
||||
"url": "http://blog.izs.me/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/core-util-is/issues"
|
||||
},
|
||||
"dependencies": {},
|
||||
"description": "The `util.is*` functions introduced in Node v0.12.",
|
||||
"devDependencies": {
|
||||
"tap": "^2.3.0"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
|
||||
"tarball": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||
},
|
||||
"gitHead": "a177da234df5638b363ddc15fa324619a38577c8",
|
||||
"homepage": "https://github.com/isaacs/core-util-is#readme",
|
||||
"keywords": [
|
||||
"util",
|
||||
"isBuffer",
|
||||
"isArray",
|
||||
"isNumber",
|
||||
"isString",
|
||||
"isRegExp",
|
||||
"isThis",
|
||||
"isThat",
|
||||
"polyfill"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/util.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
}
|
||||
],
|
||||
"name": "core-util-is",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/core-util-is.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tap test.js"
|
||||
},
|
||||
"version": "1.0.2"
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
var assert = require('tap');
|
||||
|
||||
var t = require('./lib/util');
|
||||
|
||||
assert.equal(t.isArray([]), true);
|
||||
assert.equal(t.isArray({}), false);
|
||||
|
||||
assert.equal(t.isBoolean(null), false);
|
||||
assert.equal(t.isBoolean(true), true);
|
||||
assert.equal(t.isBoolean(false), true);
|
||||
|
||||
assert.equal(t.isNull(null), true);
|
||||
assert.equal(t.isNull(undefined), false);
|
||||
assert.equal(t.isNull(false), false);
|
||||
assert.equal(t.isNull(), false);
|
||||
|
||||
assert.equal(t.isNullOrUndefined(null), true);
|
||||
assert.equal(t.isNullOrUndefined(undefined), true);
|
||||
assert.equal(t.isNullOrUndefined(false), false);
|
||||
assert.equal(t.isNullOrUndefined(), true);
|
||||
|
||||
assert.equal(t.isNumber(null), false);
|
||||
assert.equal(t.isNumber('1'), false);
|
||||
assert.equal(t.isNumber(1), true);
|
||||
|
||||
assert.equal(t.isString(null), false);
|
||||
assert.equal(t.isString('1'), true);
|
||||
assert.equal(t.isString(1), false);
|
||||
|
||||
assert.equal(t.isSymbol(null), false);
|
||||
assert.equal(t.isSymbol('1'), false);
|
||||
assert.equal(t.isSymbol(1), false);
|
||||
assert.equal(t.isSymbol(Symbol()), true);
|
||||
|
||||
assert.equal(t.isUndefined(null), false);
|
||||
assert.equal(t.isUndefined(undefined), true);
|
||||
assert.equal(t.isUndefined(false), false);
|
||||
assert.equal(t.isUndefined(), true);
|
||||
|
||||
assert.equal(t.isRegExp(null), false);
|
||||
assert.equal(t.isRegExp('1'), false);
|
||||
assert.equal(t.isRegExp(new RegExp()), true);
|
||||
|
||||
assert.equal(t.isObject({}), true);
|
||||
assert.equal(t.isObject([]), true);
|
||||
assert.equal(t.isObject(new RegExp()), true);
|
||||
assert.equal(t.isObject(new Date()), true);
|
||||
|
||||
assert.equal(t.isDate(null), false);
|
||||
assert.equal(t.isDate('1'), false);
|
||||
assert.equal(t.isDate(new Date()), true);
|
||||
|
||||
assert.equal(t.isError(null), false);
|
||||
assert.equal(t.isError({ err: true }), false);
|
||||
assert.equal(t.isError(new Error()), true);
|
||||
|
||||
assert.equal(t.isFunction(null), false);
|
||||
assert.equal(t.isFunction({ }), false);
|
||||
assert.equal(t.isFunction(function() {}), true);
|
||||
|
||||
assert.equal(t.isPrimitive(null), true);
|
||||
assert.equal(t.isPrimitive(''), true);
|
||||
assert.equal(t.isPrimitive(0), true);
|
||||
assert.equal(t.isPrimitive(new Date()), false);
|
||||
|
||||
assert.equal(t.isBuffer(null), false);
|
||||
assert.equal(t.isBuffer({}), false);
|
||||
assert.equal(t.isBuffer(new Buffer(0)), true);
|
|
@ -0,0 +1 @@
|
|||
repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"no-empty": [1, { "allowEmptyCatch": true }]
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"laxbreak": true
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
support
|
||||
test
|
||||
examples
|
||||
example
|
||||
*.sock
|
||||
dist
|
||||
yarn.lock
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "6"
|
||||
- "5"
|
||||
- "4"
|
||||
|
||||
install:
|
||||
- make node_modules
|
||||
|
||||
script:
|
||||
- make lint
|
||||
- make test
|
||||
- make coveralls
|
|
@ -0,0 +1,228 @@
|
|||
2.3.2 / 2016-11-09
|
||||
==================
|
||||
|
||||
* Fix: be super-safe in index.js as well (@TooTallNate)
|
||||
* Fix: should check whether process exists (Tom Newby)
|
||||
|
||||
2.3.1 / 2016-11-09
|
||||
==================
|
||||
|
||||
* Fix: Added electron compatibility (#324, @paulcbetts)
|
||||
* Improvement: Added performance optimizations (@tootallnate)
|
||||
* Readme: Corrected PowerShell environment variable example (#252, @gimre)
|
||||
* Misc: Removed yarn lock file from source control (#321, @fengmk2)
|
||||
|
||||
2.3.0 / 2016-11-07
|
||||
==================
|
||||
|
||||
* Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
|
||||
* Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
|
||||
* Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
|
||||
* Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
|
||||
* Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
|
||||
* Package: Update "ms" to 0.7.2 (#315, @DevSide)
|
||||
* Package: removed superfluous version property from bower.json (#207 @kkirsche)
|
||||
* Readme: fix USE_COLORS to DEBUG_COLORS
|
||||
* Readme: Doc fixes for format string sugar (#269, @mlucool)
|
||||
* Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
|
||||
* Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
|
||||
* Readme: better docs for browser support (#224, @matthewmueller)
|
||||
* Tooling: Added yarn integration for development (#317, @thebigredgeek)
|
||||
* Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
|
||||
* Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
|
||||
* Misc: Updated contributors (@thebigredgeek)
|
||||
|
||||
2.2.0 / 2015-05-09
|
||||
==================
|
||||
|
||||
* package: update "ms" to v0.7.1 (#202, @dougwilson)
|
||||
* README: add logging to file example (#193, @DanielOchoa)
|
||||
* README: fixed a typo (#191, @amir-s)
|
||||
* browser: expose `storage` (#190, @stephenmathieson)
|
||||
* Makefile: add a `distclean` target (#189, @stephenmathieson)
|
||||
|
||||
2.1.3 / 2015-03-13
|
||||
==================
|
||||
|
||||
* Updated stdout/stderr example (#186)
|
||||
* Updated example/stdout.js to match debug current behaviour
|
||||
* Renamed example/stderr.js to stdout.js
|
||||
* Update Readme.md (#184)
|
||||
* replace high intensity foreground color for bold (#182, #183)
|
||||
|
||||
2.1.2 / 2015-03-01
|
||||
==================
|
||||
|
||||
* dist: recompile
|
||||
* update "ms" to v0.7.0
|
||||
* package: update "browserify" to v9.0.3
|
||||
* component: fix "ms.js" repo location
|
||||
* changed bower package name
|
||||
* updated documentation about using debug in a browser
|
||||
* fix: security error on safari (#167, #168, @yields)
|
||||
|
||||
2.1.1 / 2014-12-29
|
||||
==================
|
||||
|
||||
* browser: use `typeof` to check for `console` existence
|
||||
* browser: check for `console.log` truthiness (fix IE 8/9)
|
||||
* browser: add support for Chrome apps
|
||||
* Readme: added Windows usage remarks
|
||||
* Add `bower.json` to properly support bower install
|
||||
|
||||
2.1.0 / 2014-10-15
|
||||
==================
|
||||
|
||||
* node: implement `DEBUG_FD` env variable support
|
||||
* package: update "browserify" to v6.1.0
|
||||
* package: add "license" field to package.json (#135, @panuhorsmalahti)
|
||||
|
||||
2.0.0 / 2014-09-01
|
||||
==================
|
||||
|
||||
* package: update "browserify" to v5.11.0
|
||||
* node: use stderr rather than stdout for logging (#29, @stephenmathieson)
|
||||
|
||||
1.0.4 / 2014-07-15
|
||||
==================
|
||||
|
||||
* dist: recompile
|
||||
* example: remove `console.info()` log usage
|
||||
* example: add "Content-Type" UTF-8 header to browser example
|
||||
* browser: place %c marker after the space character
|
||||
* browser: reset the "content" color via `color: inherit`
|
||||
* browser: add colors support for Firefox >= v31
|
||||
* debug: prefer an instance `log()` function over the global one (#119)
|
||||
* Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
|
||||
|
||||
1.0.3 / 2014-07-09
|
||||
==================
|
||||
|
||||
* Add support for multiple wildcards in namespaces (#122, @seegno)
|
||||
* browser: fix lint
|
||||
|
||||
1.0.2 / 2014-06-10
|
||||
==================
|
||||
|
||||
* browser: update color palette (#113, @gscottolson)
|
||||
* common: make console logging function configurable (#108, @timoxley)
|
||||
* node: fix %o colors on old node <= 0.8.x
|
||||
* Makefile: find node path using shell/which (#109, @timoxley)
|
||||
|
||||
1.0.1 / 2014-06-06
|
||||
==================
|
||||
|
||||
* browser: use `removeItem()` to clear localStorage
|
||||
* browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
|
||||
* package: add "contributors" section
|
||||
* node: fix comment typo
|
||||
* README: list authors
|
||||
|
||||
1.0.0 / 2014-06-04
|
||||
==================
|
||||
|
||||
* make ms diff be global, not be scope
|
||||
* debug: ignore empty strings in enable()
|
||||
* node: make DEBUG_COLORS able to disable coloring
|
||||
* *: export the `colors` array
|
||||
* npmignore: don't publish the `dist` dir
|
||||
* Makefile: refactor to use browserify
|
||||
* package: add "browserify" as a dev dependency
|
||||
* Readme: add Web Inspector Colors section
|
||||
* node: reset terminal color for the debug content
|
||||
* node: map "%o" to `util.inspect()`
|
||||
* browser: map "%j" to `JSON.stringify()`
|
||||
* debug: add custom "formatters"
|
||||
* debug: use "ms" module for humanizing the diff
|
||||
* Readme: add "bash" syntax highlighting
|
||||
* browser: add Firebug color support
|
||||
* browser: add colors for WebKit browsers
|
||||
* node: apply log to `console`
|
||||
* rewrite: abstract common logic for Node & browsers
|
||||
* add .jshintrc file
|
||||
|
||||
0.8.1 / 2014-04-14
|
||||
==================
|
||||
|
||||
* package: re-add the "component" section
|
||||
|
||||
0.8.0 / 2014-03-30
|
||||
==================
|
||||
|
||||
* add `enable()` method for nodejs. Closes #27
|
||||
* change from stderr to stdout
|
||||
* remove unnecessary index.js file
|
||||
|
||||
0.7.4 / 2013-11-13
|
||||
==================
|
||||
|
||||
* remove "browserify" key from package.json (fixes something in browserify)
|
||||
|
||||
0.7.3 / 2013-10-30
|
||||
==================
|
||||
|
||||
* fix: catch localStorage security error when cookies are blocked (Chrome)
|
||||
* add debug(err) support. Closes #46
|
||||
* add .browser prop to package.json. Closes #42
|
||||
|
||||
0.7.2 / 2013-02-06
|
||||
==================
|
||||
|
||||
* fix package.json
|
||||
* fix: Mobile Safari (private mode) is broken with debug
|
||||
* fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
|
||||
|
||||
0.7.1 / 2013-02-05
|
||||
==================
|
||||
|
||||
* add repository URL to package.json
|
||||
* add DEBUG_COLORED to force colored output
|
||||
* add browserify support
|
||||
* fix component. Closes #24
|
||||
|
||||
0.7.0 / 2012-05-04
|
||||
==================
|
||||
|
||||
* Added .component to package.json
|
||||
* Added debug.component.js build
|
||||
|
||||
0.6.0 / 2012-03-16
|
||||
==================
|
||||
|
||||
* Added support for "-" prefix in DEBUG [Vinay Pulim]
|
||||
* Added `.enabled` flag to the node version [TooTallNate]
|
||||
|
||||
0.5.0 / 2012-02-02
|
||||
==================
|
||||
|
||||
* Added: humanize diffs. Closes #8
|
||||
* Added `debug.disable()` to the CS variant
|
||||
* Removed padding. Closes #10
|
||||
* Fixed: persist client-side variant again. Closes #9
|
||||
|
||||
0.4.0 / 2012-02-01
|
||||
==================
|
||||
|
||||
* Added browser variant support for older browsers [TooTallNate]
|
||||
* Added `debug.enable('project:*')` to browser variant [TooTallNate]
|
||||
* Added padding to diff (moved it to the right)
|
||||
|
||||
0.3.0 / 2012-01-26
|
||||
==================
|
||||
|
||||
* Added millisecond diff when isatty, otherwise UTC string
|
||||
|
||||
0.2.0 / 2012-01-22
|
||||
==================
|
||||
|
||||
* Added wildcard support
|
||||
|
||||
0.1.0 / 2011-12-02
|
||||
==================
|
||||
|
||||
* Added: remove colors unless stderr isatty [TooTallNate]
|
||||
|
||||
0.0.1 / 2010-01-03
|
||||
==================
|
||||
|
||||
* Initial release
|
|
@ -0,0 +1,19 @@
|
|||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
and associated documentation files (the 'Software'), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
|
||||
THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
||||
THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
|
||||
|
||||
# BIN directory
|
||||
BIN := $(THIS_DIR)/node_modules/.bin
|
||||
|
||||
# applications
|
||||
NODE ?= $(shell which node)
|
||||
YARN ?= $(shell which yarn)
|
||||
PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
|
||||
BROWSERIFY ?= $(NODE) $(BIN)/browserify
|
||||
|
||||
all: dist/debug.js
|
||||
|
||||
install: node_modules
|
||||
|
||||
clean:
|
||||
@rm -rf dist
|
||||
|
||||
dist:
|
||||
@mkdir -p $@
|
||||
|
||||
dist/debug.js: node_modules browser.js debug.js dist
|
||||
@$(BROWSERIFY) \
|
||||
--standalone debug \
|
||||
. > $@
|
||||
|
||||
distclean: clean
|
||||
@rm -rf node_modules
|
||||
|
||||
node_modules: package.json
|
||||
@NODE_ENV= $(PKG) install
|
||||
@touch node_modules
|
||||
|
||||
.PHONY: all install clean distclean
|
|
@ -0,0 +1,238 @@
|
|||
# debug
|
||||
[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master)
|
||||
|
||||
A tiny node.js debugging utility modelled after node core's debugging technique.
|
||||
|
||||
**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install debug
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
|
||||
|
||||
Example _app.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %s', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
||||
```
|
||||
|
||||
Example _worker.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('worker');
|
||||
|
||||
setInterval(function(){
|
||||
debug('doing some work');
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
|
||||
|
||||
![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
|
||||
|
||||
![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
|
||||
|
||||
#### Windows note
|
||||
|
||||
On Windows the environment variable is set using the `set` command.
|
||||
|
||||
```cmd
|
||||
set DEBUG=*,-not_this
|
||||
```
|
||||
|
||||
Note that PowerShell uses different syntax to set environment variables.
|
||||
|
||||
```cmd
|
||||
$env:DEBUG = "*,-not_this"
|
||||
```
|
||||
|
||||
Then, run the program to be debugged as usual.
|
||||
|
||||
## Millisecond diff
|
||||
|
||||
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
|
||||
|
||||
![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
|
||||
|
||||
When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
|
||||
|
||||
![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
|
||||
|
||||
## Conventions
|
||||
|
||||
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
|
||||
|
||||
## Wildcards
|
||||
|
||||
The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
|
||||
|
||||
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
|
||||
|
||||
## Environment Variables
|
||||
|
||||
When running through Node.js, you can set a few environment variables that will
|
||||
change the behavior of the debug logging:
|
||||
|
||||
| Name | Purpose |
|
||||
|-----------|-------------------------------------------------|
|
||||
| `DEBUG` | Enables/disabled specific debugging namespaces. |
|
||||
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
|
||||
| `DEBUG_DEPTH` | Object inspection depth. |
|
||||
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
|
||||
|
||||
|
||||
__Note:__ The environment variables beginning with `DEBUG_` end up being
|
||||
converted into an Options object that gets used with `%o`/`%O` formatters.
|
||||
See the Node.js documentation for
|
||||
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
|
||||
for the complete list.
|
||||
|
||||
## Formatters
|
||||
|
||||
|
||||
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
|
||||
|
||||
| Formatter | Representation |
|
||||
|-----------|----------------|
|
||||
| `%O` | Pretty-print an Object on multiple lines. |
|
||||
| `%o` | Pretty-print an Object all on a single line. |
|
||||
| `%s` | String. |
|
||||
| `%d` | Number (both integer and float). |
|
||||
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
|
||||
| `%%` | Single percent sign ('%'). This does not consume an argument. |
|
||||
|
||||
### Custom formatters
|
||||
|
||||
You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
|
||||
|
||||
```js
|
||||
const createDebug = require('debug')
|
||||
createDebug.formatters.h = (v) => {
|
||||
return v.toString('hex')
|
||||
}
|
||||
|
||||
// …elsewhere
|
||||
const debug = createDebug('foo')
|
||||
debug('this is hex: %h', new Buffer('hello world'))
|
||||
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
|
||||
```
|
||||
|
||||
## Browser support
|
||||
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
|
||||
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
|
||||
if you don't want to build it yourself.
|
||||
|
||||
Debug's enable state is currently persisted by `localStorage`.
|
||||
Consider the situation shown below where you have `worker:a` and `worker:b`,
|
||||
and wish to debug both. You can enable this using `localStorage.debug`:
|
||||
|
||||
```js
|
||||
localStorage.debug = 'worker:*'
|
||||
```
|
||||
|
||||
And then refresh the page.
|
||||
|
||||
```js
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
b('doing some work');
|
||||
}, 1200);
|
||||
```
|
||||
|
||||
#### Web Inspector Colors
|
||||
|
||||
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
|
||||
option. These are WebKit web inspectors, Firefox ([since version
|
||||
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
|
||||
and the Firebug plugin for Firefox (any version).
|
||||
|
||||
Colored output looks something like:
|
||||
|
||||
![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
|
||||
|
||||
|
||||
## Output streams
|
||||
|
||||
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
|
||||
|
||||
Example _stdout.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug');
|
||||
var error = debug('app:error');
|
||||
|
||||
// by default stderr is used
|
||||
error('goes to stderr!');
|
||||
|
||||
var log = debug('app:log');
|
||||
// set this namespace to log via console.log
|
||||
log.log = console.log.bind(console); // don't forget to bind to console!
|
||||
log('goes to stdout');
|
||||
error('still goes to stderr!');
|
||||
|
||||
// set all output to go via console.info
|
||||
// overrides all per-namespace log settings
|
||||
debug.log = console.info.bind(console);
|
||||
error('now goes to stdout via console.info');
|
||||
log('still goes to stdout, but via console.info now');
|
||||
```
|
||||
|
||||
|
||||
## Authors
|
||||
|
||||
- TJ Holowaychuk
|
||||
- Nathan Rajlich
|
||||
- Andrew Rhyne
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,199 @@
|
|||
# debug
|
||||
|
||||
tiny node.js debugging utility modelled after node core's debugging technique.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install debug
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` [format string goodies](https://developer.chrome.com/devtools/docs/console-api#consolelogobject-object) you're used to work fine. A unique color is selected per-function for visibility.
|
||||
|
||||
Example _app.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('http')
|
||||
, http = require('http')
|
||||
, name = 'My App';
|
||||
|
||||
// fake app
|
||||
|
||||
debug('booting %s', name);
|
||||
|
||||
http.createServer(function(req, res){
|
||||
debug(req.method + ' ' + req.url);
|
||||
res.end('hello\n');
|
||||
}).listen(3000, function(){
|
||||
debug('listening');
|
||||
});
|
||||
|
||||
// fake worker of some kind
|
||||
|
||||
require('./worker');
|
||||
```
|
||||
|
||||
Example _worker.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug')('worker');
|
||||
|
||||
setInterval(function(){
|
||||
debug('doing some work');
|
||||
}, 1000);
|
||||
```
|
||||
|
||||
The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
|
||||
|
||||
![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
|
||||
|
||||
![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
|
||||
|
||||
#### Windows note
|
||||
|
||||
On Windows the environment variable is set using the `set` command.
|
||||
|
||||
```cmd
|
||||
set DEBUG=*,-not_this
|
||||
```
|
||||
|
||||
Note that PowerShell using different syntax to set environment variables.
|
||||
|
||||
```cmd
|
||||
$env:DEBUG = "*,-not_this"
|
||||
```
|
||||
|
||||
Then, run the program to be debugged as usual.
|
||||
|
||||
## Millisecond diff
|
||||
|
||||
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
|
||||
|
||||
![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
|
||||
|
||||
When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
|
||||
|
||||
![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
|
||||
|
||||
## Conventions
|
||||
|
||||
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
|
||||
|
||||
## Wildcards
|
||||
|
||||
The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
|
||||
|
||||
You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
|
||||
|
||||
## Browser support
|
||||
|
||||
Debug works in the browser as well, currently persisted by `localStorage`. Consider the situation shown below where you have `worker:a` and `worker:b`, and wish to debug both. You can enable this using `localStorage.debug`:
|
||||
|
||||
```js
|
||||
localStorage.debug = 'worker:*'
|
||||
```
|
||||
|
||||
And then refresh the page.
|
||||
|
||||
```js
|
||||
a = debug('worker:a');
|
||||
b = debug('worker:b');
|
||||
|
||||
setInterval(function(){
|
||||
a('doing some work');
|
||||
}, 1000);
|
||||
|
||||
setInterval(function(){
|
||||
b('doing some work');
|
||||
}, 1200);
|
||||
```
|
||||
|
||||
#### Web Inspector Colors
|
||||
|
||||
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
|
||||
option. These are WebKit web inspectors, Firefox ([since version
|
||||
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
|
||||
and the Firebug plugin for Firefox (any version).
|
||||
|
||||
Colored output looks something like:
|
||||
|
||||
![](https://cloud.githubusercontent.com/assets/71256/3139768/b98c5fd8-e8ef-11e3-862a-f7253b6f47c6.png)
|
||||
|
||||
## Output streams
|
||||
|
||||
|
||||
### stderr vs stdout
|
||||
By default `debug` will log to stderr, however this can be changed by setting the environment variable `DEBUG_FD` to `1` for stdout and `2` for stderr (the default value).
|
||||
|
||||
You can also set an alternative logging method per-namespace by overriding the `log` method on a per-namespace or globally:
|
||||
|
||||
Example _stdout.js_:
|
||||
|
||||
```js
|
||||
var debug = require('debug');
|
||||
var error = debug('app:error');
|
||||
|
||||
// by default stderr is used
|
||||
error('goes to stderr!');
|
||||
|
||||
var log = debug('app:log');
|
||||
// set this namespace to log via console.log
|
||||
log.log = console.log.bind(console); // don't forget to bind to console!
|
||||
log('goes to stdout');
|
||||
error('still goes to stderr!');
|
||||
|
||||
// set all output to go via console.info
|
||||
// overrides all per-namespace log settings
|
||||
debug.log = console.info.bind(console);
|
||||
error('now goes to stdout via console.info');
|
||||
log('still goes to stdout, but via console.info now');
|
||||
```
|
||||
|
||||
### Save debug output to a file
|
||||
|
||||
You can save all debug statements to a file by piping them.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
$ DEBUG_FD=3 node your-app.js 3> whatever.log
|
||||
```
|
||||
|
||||
### Terminal colors
|
||||
|
||||
By default colors will only be used in a TTY. However this can be overridden by setting the environment variable `DEBUG_COLORS` to `1`.
|
||||
|
||||
Note: Certain IDEs (such as WebStorm) don't support colors on stderr. In these cases you must set `DEBUG_COLORS` to `1` and additionally change `DEBUG_FD` to `1`.
|
||||
|
||||
## Authors
|
||||
|
||||
- TJ Holowaychuk
|
||||
- Nathan Rajlich
|
||||
- Andrew Rhyne
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "visionmedia-debug",
|
||||
"main": "dist/debug.js",
|
||||
"homepage": "https://github.com/visionmedia/debug",
|
||||
"authors": [
|
||||
"TJ Holowaychuk <tj@vision-media.ca>",
|
||||
"Nathan Rajlich <nathan@tootallnate.net> (http://n8.io)",
|
||||
"Andrew Rhyne <rhyneandrew@gmail.com>"
|
||||
],
|
||||
"description": "visionmedia-debug",
|
||||
"moduleType": [
|
||||
"amd",
|
||||
"es6",
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"visionmedia",
|
||||
"debug"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
|
||||
/**
|
||||
* This is the web browser implementation of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = require('./debug');
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.storage = 'undefined' != typeof chrome
|
||||
&& 'undefined' != typeof chrome.storage
|
||||
? chrome.storage.local
|
||||
: localstorage();
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [
|
||||
'lightseagreen',
|
||||
'forestgreen',
|
||||
'goldenrod',
|
||||
'dodgerblue',
|
||||
'darkorchid',
|
||||
'crimson'
|
||||
];
|
||||
|
||||
/**
|
||||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||||
* and the Firebug extension (any Firefox version) are known
|
||||
* to support "%c" CSS customizations.
|
||||
*
|
||||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
// is webkit? http://stackoverflow.com/a/16459606/376773
|
||||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||
return (typeof document !== 'undefined' && 'WebkitAppearance' in document.documentElement.style) ||
|
||||
// is firebug? http://stackoverflow.com/a/398120/376773
|
||||
(window.console && (console.firebug || (console.exception && console.table))) ||
|
||||
// is firefox >= v31?
|
||||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||
(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||||
*/
|
||||
|
||||
exports.formatters.j = function(v) {
|
||||
return JSON.stringify(v);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Colorize log arguments if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs() {
|
||||
var args = arguments;
|
||||
var useColors = this.useColors;
|
||||
|
||||
args[0] = (useColors ? '%c' : '')
|
||||
+ this.namespace
|
||||
+ (useColors ? ' %c' : ' ')
|
||||
+ args[0]
|
||||
+ (useColors ? '%c ' : ' ')
|
||||
+ '+' + exports.humanize(this.diff);
|
||||
|
||||
if (!useColors) return args;
|
||||
|
||||
var c = 'color: ' + this.color;
|
||||
args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
|
||||
|
||||
// the final "%c" is somewhat tricky, because there could be other
|
||||
// arguments passed either before or after the %c, so we need to
|
||||
// figure out the correct index to insert the CSS into
|
||||
var index = 0;
|
||||
var lastC = 0;
|
||||
args[0].replace(/%[a-z%]/g, function(match) {
|
||||
if ('%%' === match) return;
|
||||
index++;
|
||||
if ('%c' === match) {
|
||||
// we only are interested in the *last* %c
|
||||
// (the user may have provided their own)
|
||||
lastC = index;
|
||||
}
|
||||
});
|
||||
|
||||
args.splice(lastC, 0, c);
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `console.log()` when available.
|
||||
* No-op when `console.log` is not a "function".
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function log() {
|
||||
// this hackery is required for IE8/9, where
|
||||
// the `console.log` function doesn't have 'apply'
|
||||
return 'object' === typeof console
|
||||
&& console.log
|
||||
&& Function.prototype.apply.call(console.log, console, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function save(namespaces) {
|
||||
try {
|
||||
if (null == namespaces) {
|
||||
exports.storage.removeItem('debug');
|
||||
} else {
|
||||
exports.storage.debug = namespaces;
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
var r;
|
||||
try {
|
||||
r = exports.storage.debug;
|
||||
} catch(e) {}
|
||||
|
||||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||||
if ('env' in (typeof process === 'undefined' ? {} : process)) {
|
||||
r = process.env.DEBUG;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable namespaces listed in `localStorage.debug` initially.
|
||||
*/
|
||||
|
||||
exports.enable(load());
|
||||
|
||||
/**
|
||||
* Localstorage attempts to return the localstorage.
|
||||
*
|
||||
* This is necessary because safari throws
|
||||
* when a user disables cookies/localstorage
|
||||
* and you attempt to access it.
|
||||
*
|
||||
* @return {LocalStorage}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function localstorage(){
|
||||
try {
|
||||
return window.localStorage;
|
||||
} catch (e) {}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "debug",
|
||||
"repo": "visionmedia/debug",
|
||||
"description": "small debugging utility",
|
||||
"version": "2.3.2",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"log",
|
||||
"debugger"
|
||||
],
|
||||
"main": "browser.js",
|
||||
"scripts": [
|
||||
"browser.js",
|
||||
"debug.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"rauchg/ms.js": "0.7.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
|
||||
/**
|
||||
* This is the common logic for both the Node.js and web browser
|
||||
* implementations of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = debug.debug = debug;
|
||||
exports.coerce = coerce;
|
||||
exports.disable = disable;
|
||||
exports.enable = enable;
|
||||
exports.enabled = enabled;
|
||||
exports.humanize = require('ms');
|
||||
|
||||
/**
|
||||
* The currently active debug mode names, and names to skip.
|
||||
*/
|
||||
|
||||
exports.names = [];
|
||||
exports.skips = [];
|
||||
|
||||
/**
|
||||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||||
*
|
||||
* Valid key names are a single, lowercased letter, i.e. "n".
|
||||
*/
|
||||
|
||||
exports.formatters = {};
|
||||
|
||||
/**
|
||||
* Previously assigned color.
|
||||
*/
|
||||
|
||||
var prevColor = 0;
|
||||
|
||||
/**
|
||||
* Previous log timestamp.
|
||||
*/
|
||||
|
||||
var prevTime;
|
||||
|
||||
/**
|
||||
* Select a color.
|
||||
*
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function selectColor() {
|
||||
return exports.colors[prevColor++ % exports.colors.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `namespace`.
|
||||
*
|
||||
* @param {String} namespace
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function debug(namespace) {
|
||||
|
||||
// define the `disabled` version
|
||||
function disabled() {
|
||||
}
|
||||
disabled.enabled = false;
|
||||
|
||||
// define the `enabled` version
|
||||
function enabled() {
|
||||
|
||||
var self = enabled;
|
||||
|
||||
// set `diff` timestamp
|
||||
var curr = +new Date();
|
||||
var ms = curr - (prevTime || curr);
|
||||
self.diff = ms;
|
||||
self.prev = prevTime;
|
||||
self.curr = curr;
|
||||
prevTime = curr;
|
||||
|
||||
// add the `color` if not set
|
||||
if (null == self.useColors) self.useColors = exports.useColors();
|
||||
if (null == self.color && self.useColors) self.color = selectColor();
|
||||
|
||||
var args = new Array(arguments.length);
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
args[0] = exports.coerce(args[0]);
|
||||
|
||||
if ('string' !== typeof args[0]) {
|
||||
// anything else let's inspect with %o
|
||||
args = ['%o'].concat(args);
|
||||
}
|
||||
|
||||
// apply any `formatters` transformations
|
||||
var index = 0;
|
||||
args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
|
||||
// if we encounter an escaped % then don't increase the array index
|
||||
if (match === '%%') return match;
|
||||
index++;
|
||||
var formatter = exports.formatters[format];
|
||||
if ('function' === typeof formatter) {
|
||||
var val = args[index];
|
||||
match = formatter.call(self, val);
|
||||
|
||||
// now we need to remove `args[index]` since it's inlined in the `format`
|
||||
args.splice(index, 1);
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
// apply env-specific formatting
|
||||
args = exports.formatArgs.apply(self, args);
|
||||
|
||||
var logFn = enabled.log || exports.log || console.log.bind(console);
|
||||
logFn.apply(self, args);
|
||||
}
|
||||
enabled.enabled = true;
|
||||
|
||||
var fn = exports.enabled(namespace) ? enabled : disabled;
|
||||
|
||||
fn.namespace = namespace;
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a debug mode by namespaces. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function enable(namespaces) {
|
||||
exports.save(namespaces);
|
||||
|
||||
var split = (namespaces || '').split(/[\s,]+/);
|
||||
var len = split.length;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (!split[i]) continue; // ignore empty strings
|
||||
namespaces = split[i].replace(/[\\^$+?.()|[\]{}]/g, '\\$&').replace(/\*/g, '.*?');
|
||||
if (namespaces[0] === '-') {
|
||||
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
||||
} else {
|
||||
exports.names.push(new RegExp('^' + namespaces + '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function disable() {
|
||||
exports.enable('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function enabled(name) {
|
||||
var i, len;
|
||||
for (i = 0, len = exports.skips.length; i < len; i++) {
|
||||
if (exports.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0, len = exports.names.length; i < len; i++) {
|
||||
if (exports.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerce `val`.
|
||||
*
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function coerce(val) {
|
||||
if (val instanceof Error) return val.stack || val.message;
|
||||
return val;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Detect Electron renderer process, which is node, but we should
|
||||
* treat as a browser.
|
||||
*/
|
||||
|
||||
if ((typeof process === 'undefined' ? {} : process).type === 'renderer') {
|
||||
module.exports = require('./browser.js');
|
||||
} else {
|
||||
module.exports = require('./node.js');
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Karma configuration
|
||||
// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: '',
|
||||
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['mocha', 'chai', 'sinon'],
|
||||
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'dist/debug.js',
|
||||
'test/*spec.js'
|
||||
],
|
||||
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
'src/node.js'
|
||||
],
|
||||
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['progress'],
|
||||
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity
|
||||
})
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var tty = require('tty');
|
||||
var util = require('util');
|
||||
|
||||
/**
|
||||
* This is the Node.js implementation of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = require('./debug');
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||||
|
||||
/**
|
||||
* The file descriptor to write the `debug()` calls to.
|
||||
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
|
||||
*
|
||||
* $ DEBUG_FD=3 node script.js 3>debug.log
|
||||
*/
|
||||
|
||||
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
|
||||
var stream = 1 === fd ? process.stdout :
|
||||
2 === fd ? process.stderr :
|
||||
createWritableStdioStream(fd);
|
||||
|
||||
/**
|
||||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
var debugColors = (process.env.DEBUG_COLORS || '').trim().toLowerCase();
|
||||
if (0 === debugColors.length) {
|
||||
return tty.isatty(fd);
|
||||
} else {
|
||||
return '0' !== debugColors
|
||||
&& 'no' !== debugColors
|
||||
&& 'false' !== debugColors
|
||||
&& 'disabled' !== debugColors;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map %o to `util.inspect()`, since Node doesn't do that out of the box.
|
||||
*/
|
||||
|
||||
var inspect = (4 === util.inspect.length ?
|
||||
// node <= 0.8.x
|
||||
function (v, colors) {
|
||||
return util.inspect(v, void 0, void 0, colors);
|
||||
} :
|
||||
// node > 0.8.x
|
||||
function (v, colors) {
|
||||
return util.inspect(v, { colors: colors });
|
||||
}
|
||||
);
|
||||
|
||||
exports.formatters.o = exports.formatters.O = function(v) {
|
||||
return inspect(v, this.useColors)
|
||||
.replace(/\s*\n\s*/g, ' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds ANSI color escape codes if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs() {
|
||||
var len = arguments.length;
|
||||
var args = new Array(len);
|
||||
var useColors = this.useColors;
|
||||
var name = this.namespace;
|
||||
for (var i = 0; i < len; i++) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
if (useColors) {
|
||||
var c = this.color;
|
||||
|
||||
args[0] = ' \u001b[3' + c + ';1m' + name + ' '
|
||||
+ '\u001b[0m'
|
||||
+ args[0];
|
||||
args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
|
||||
} else {
|
||||
args[0] = new Date().toUTCString()
|
||||
+ ' ' + name + ' ' + args[0];
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `console.error()` with the specified arguments.
|
||||
*/
|
||||
|
||||
function log() {
|
||||
return stream.write(util.format.apply(this, arguments) + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function save(namespaces) {
|
||||
if (null == namespaces) {
|
||||
// If you set a process.env field to null or undefined, it gets cast to the
|
||||
// string 'null' or 'undefined'. Just delete instead.
|
||||
delete process.env.DEBUG;
|
||||
} else {
|
||||
process.env.DEBUG = namespaces;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
return process.env.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from `node/src/node.js`.
|
||||
*
|
||||
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also
|
||||
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
|
||||
*/
|
||||
|
||||
function createWritableStdioStream (fd) {
|
||||
var stream;
|
||||
var tty_wrap = process.binding('tty_wrap');
|
||||
|
||||
// Note stream._type is used for test-module-load-list.js
|
||||
|
||||
switch (tty_wrap.guessHandleType(fd)) {
|
||||
case 'TTY':
|
||||
stream = new tty.WriteStream(fd);
|
||||
stream._type = 'tty';
|
||||
|
||||
// Hack to have stream not keep the event loop alive.
|
||||
// See https://github.com/joyent/node/issues/1726
|
||||
if (stream._handle && stream._handle.unref) {
|
||||
stream._handle.unref();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FILE':
|
||||
var fs = require('fs');
|
||||
stream = new fs.SyncWriteStream(fd, { autoClose: false });
|
||||
stream._type = 'fs';
|
||||
break;
|
||||
|
||||
case 'PIPE':
|
||||
case 'TCP':
|
||||
var net = require('net');
|
||||
stream = new net.Socket({
|
||||
fd: fd,
|
||||
readable: false,
|
||||
writable: true
|
||||
});
|
||||
|
||||
// FIXME Should probably have an option in net.Socket to create a
|
||||
// stream from an existing fd which is writable only. But for now
|
||||
// we'll just add this hack and set the `readable` member to false.
|
||||
// Test: ./node test/fixtures/echo.js < /etc/passwd
|
||||
stream.readable = false;
|
||||
stream.read = null;
|
||||
stream._type = 'pipe';
|
||||
|
||||
// FIXME Hack to have stream not keep the event loop alive.
|
||||
// See https://github.com/joyent/node/issues/1726
|
||||
if (stream._handle && stream._handle.unref) {
|
||||
stream._handle.unref();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Probably an error on in uv_guess_handle()
|
||||
throw new Error('Implement me. Unknown stream file type!');
|
||||
}
|
||||
|
||||
// For supporting legacy API we put the FD here.
|
||||
stream.fd = fd;
|
||||
|
||||
stream._isStdio = true;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable namespaces listed in `process.env.DEBUG` initially.
|
||||
*/
|
||||
|
||||
exports.enable(load());
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "debug@^2.1.0",
|
||||
"scope": null,
|
||||
"escapedName": "debug",
|
||||
"name": "debug",
|
||||
"rawSpec": "^2.1.0",
|
||||
"spec": ">=2.1.0 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"/srv/demos/node_modules/dns-js"
|
||||
]
|
||||
],
|
||||
"_from": "debug@>=2.1.0 <3.0.0",
|
||||
"_id": "debug@2.3.2",
|
||||
"_inCache": true,
|
||||
"_location": "/debug",
|
||||
"_nodeVersion": "7.0.0",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-18-east.internal.npmjs.com",
|
||||
"tmp": "tmp/debug-2.3.2.tgz_1478759402178_0.8417916153557599"
|
||||
},
|
||||
"_npmUser": {
|
||||
"name": "tootallnate",
|
||||
"email": "nathan@tootallnate.net"
|
||||
},
|
||||
"_npmVersion": "3.10.8",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "debug@^2.1.0",
|
||||
"scope": null,
|
||||
"escapedName": "debug",
|
||||
"name": "debug",
|
||||
"rawSpec": "^2.1.0",
|
||||
"spec": ">=2.1.0 <3.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/dns-js"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/debug/-/debug-2.3.2.tgz",
|
||||
"_shasum": "94cb466ef7d6d2c7e5245cdd6e4104f2d0d70d30",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "debug@^2.1.0",
|
||||
"_where": "/srv/demos/node_modules/dns-js",
|
||||
"author": {
|
||||
"name": "TJ Holowaychuk",
|
||||
"email": "tj@vision-media.ca"
|
||||
},
|
||||
"browser": "./browser.js",
|
||||
"bugs": {
|
||||
"url": "https://github.com/visionmedia/debug/issues"
|
||||
},
|
||||
"component": {
|
||||
"scripts": {
|
||||
"debug/index.js": "browser.js",
|
||||
"debug/debug.js": "debug.js"
|
||||
}
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Nathan Rajlich",
|
||||
"email": "nathan@tootallnate.net",
|
||||
"url": "http://n8.io"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Rhyne",
|
||||
"email": "rhyneandrew@gmail.com"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"ms": "0.7.2"
|
||||
},
|
||||
"description": "small debugging utility",
|
||||
"devDependencies": {
|
||||
"browserify": "9.0.3",
|
||||
"mocha": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "94cb466ef7d6d2c7e5245cdd6e4104f2d0d70d30",
|
||||
"tarball": "https://registry.npmjs.org/debug/-/debug-2.3.2.tgz"
|
||||
},
|
||||
"gitHead": "1c6f45840d0dba8cb14f9975b4633bb685fda400",
|
||||
"homepage": "https://github.com/visionmedia/debug#readme",
|
||||
"keywords": [
|
||||
"debug",
|
||||
"log",
|
||||
"debugger"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "./index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "kolban",
|
||||
"email": "kolban1@kolban.com"
|
||||
},
|
||||
{
|
||||
"name": "thebigredgeek",
|
||||
"email": "rhyneandrew@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "tjholowaychuk",
|
||||
"email": "tj@vision-media.ca"
|
||||
},
|
||||
{
|
||||
"name": "tootallnate",
|
||||
"email": "nathan@tootallnate.net"
|
||||
}
|
||||
],
|
||||
"name": "debug",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/visionmedia/debug.git"
|
||||
},
|
||||
"scripts": {},
|
||||
"version": "2.3.2"
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
* This is the web browser implementation of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = require('./debug');
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
exports.storage = 'undefined' != typeof chrome
|
||||
&& 'undefined' != typeof chrome.storage
|
||||
? chrome.storage.local
|
||||
: localstorage();
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [
|
||||
'lightseagreen',
|
||||
'forestgreen',
|
||||
'goldenrod',
|
||||
'dodgerblue',
|
||||
'darkorchid',
|
||||
'crimson'
|
||||
];
|
||||
|
||||
/**
|
||||
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
||||
* and the Firebug extension (any Firefox version) are known
|
||||
* to support "%c" CSS customizations.
|
||||
*
|
||||
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
// NB: In an Electron preload script, document will be defined but not fully
|
||||
// initialized. Since we know we're in Chrome, we'll just detect this case
|
||||
// explicitly
|
||||
if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// is webkit? http://stackoverflow.com/a/16459606/376773
|
||||
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
||||
return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
|
||||
// is firebug? http://stackoverflow.com/a/398120/376773
|
||||
(typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
|
||||
// is firefox >= v31?
|
||||
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
||||
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
||||
// double check webkit in userAgent just in case we are in a worker
|
||||
(typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
||||
}
|
||||
|
||||
/**
|
||||
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
||||
*/
|
||||
|
||||
exports.formatters.j = function(v) {
|
||||
try {
|
||||
return JSON.stringify(v);
|
||||
} catch (err) {
|
||||
return '[UnexpectedJSONParseError]: ' + err.message;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Colorize log arguments if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
var useColors = this.useColors;
|
||||
|
||||
args[0] = (useColors ? '%c' : '')
|
||||
+ this.namespace
|
||||
+ (useColors ? ' %c' : ' ')
|
||||
+ args[0]
|
||||
+ (useColors ? '%c ' : ' ')
|
||||
+ '+' + exports.humanize(this.diff);
|
||||
|
||||
if (!useColors) return;
|
||||
|
||||
var c = 'color: ' + this.color;
|
||||
args.splice(1, 0, c, 'color: inherit')
|
||||
|
||||
// the final "%c" is somewhat tricky, because there could be other
|
||||
// arguments passed either before or after the %c, so we need to
|
||||
// figure out the correct index to insert the CSS into
|
||||
var index = 0;
|
||||
var lastC = 0;
|
||||
args[0].replace(/%[a-zA-Z%]/g, function(match) {
|
||||
if ('%%' === match) return;
|
||||
index++;
|
||||
if ('%c' === match) {
|
||||
// we only are interested in the *last* %c
|
||||
// (the user may have provided their own)
|
||||
lastC = index;
|
||||
}
|
||||
});
|
||||
|
||||
args.splice(lastC, 0, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `console.log()` when available.
|
||||
* No-op when `console.log` is not a "function".
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function log() {
|
||||
// this hackery is required for IE8/9, where
|
||||
// the `console.log` function doesn't have 'apply'
|
||||
return 'object' === typeof console
|
||||
&& console.log
|
||||
&& Function.prototype.apply.call(console.log, console, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function save(namespaces) {
|
||||
try {
|
||||
if (null == namespaces) {
|
||||
exports.storage.removeItem('debug');
|
||||
} else {
|
||||
exports.storage.debug = namespaces;
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
try {
|
||||
return exports.storage.debug;
|
||||
} catch(e) {}
|
||||
|
||||
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
||||
if (typeof process !== 'undefined' && 'env' in process) {
|
||||
return process.env.DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable namespaces listed in `localStorage.debug` initially.
|
||||
*/
|
||||
|
||||
exports.enable(load());
|
||||
|
||||
/**
|
||||
* Localstorage attempts to return the localstorage.
|
||||
*
|
||||
* This is necessary because safari throws
|
||||
* when a user disables cookies/localstorage
|
||||
* and you attempt to access it.
|
||||
*
|
||||
* @return {LocalStorage}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function localstorage() {
|
||||
try {
|
||||
return window.localStorage;
|
||||
} catch (e) {}
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
|
||||
/**
|
||||
* This is the common logic for both the Node.js and web browser
|
||||
* implementations of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = createDebug.debug = createDebug.default = createDebug;
|
||||
exports.coerce = coerce;
|
||||
exports.disable = disable;
|
||||
exports.enable = enable;
|
||||
exports.enabled = enabled;
|
||||
exports.humanize = require('ms');
|
||||
|
||||
/**
|
||||
* The currently active debug mode names, and names to skip.
|
||||
*/
|
||||
|
||||
exports.names = [];
|
||||
exports.skips = [];
|
||||
|
||||
/**
|
||||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||||
*
|
||||
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
||||
*/
|
||||
|
||||
exports.formatters = {};
|
||||
|
||||
/**
|
||||
* Previous log timestamp.
|
||||
*/
|
||||
|
||||
var prevTime;
|
||||
|
||||
/**
|
||||
* Select a color.
|
||||
* @param {String} namespace
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function selectColor(namespace) {
|
||||
var hash = 0, i;
|
||||
|
||||
for (i in namespace) {
|
||||
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
||||
hash |= 0; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return exports.colors[Math.abs(hash) % exports.colors.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a debugger with the given `namespace`.
|
||||
*
|
||||
* @param {String} namespace
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function createDebug(namespace) {
|
||||
|
||||
function debug() {
|
||||
// disabled?
|
||||
if (!debug.enabled) return;
|
||||
|
||||
var self = debug;
|
||||
|
||||
// set `diff` timestamp
|
||||
var curr = +new Date();
|
||||
var ms = curr - (prevTime || curr);
|
||||
self.diff = ms;
|
||||
self.prev = prevTime;
|
||||
self.curr = curr;
|
||||
prevTime = curr;
|
||||
|
||||
// turn the `arguments` into a proper Array
|
||||
var args = new Array(arguments.length);
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
args[i] = arguments[i];
|
||||
}
|
||||
|
||||
args[0] = exports.coerce(args[0]);
|
||||
|
||||
if ('string' !== typeof args[0]) {
|
||||
// anything else let's inspect with %O
|
||||
args.unshift('%O');
|
||||
}
|
||||
|
||||
// apply any `formatters` transformations
|
||||
var index = 0;
|
||||
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
|
||||
// if we encounter an escaped % then don't increase the array index
|
||||
if (match === '%%') return match;
|
||||
index++;
|
||||
var formatter = exports.formatters[format];
|
||||
if ('function' === typeof formatter) {
|
||||
var val = args[index];
|
||||
match = formatter.call(self, val);
|
||||
|
||||
// now we need to remove `args[index]` since it's inlined in the `format`
|
||||
args.splice(index, 1);
|
||||
index--;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
|
||||
// apply env-specific formatting (colors, etc.)
|
||||
exports.formatArgs.call(self, args);
|
||||
|
||||
var logFn = debug.log || exports.log || console.log.bind(console);
|
||||
logFn.apply(self, args);
|
||||
}
|
||||
|
||||
debug.namespace = namespace;
|
||||
debug.enabled = exports.enabled(namespace);
|
||||
debug.useColors = exports.useColors();
|
||||
debug.color = selectColor(namespace);
|
||||
|
||||
// env-specific initialization logic for debug instances
|
||||
if ('function' === typeof exports.init) {
|
||||
exports.init(debug);
|
||||
}
|
||||
|
||||
return debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a debug mode by namespaces. This can include modes
|
||||
* separated by a colon and wildcards.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function enable(namespaces) {
|
||||
exports.save(namespaces);
|
||||
|
||||
var split = (namespaces || '').split(/[\s,]+/);
|
||||
var len = split.length;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (!split[i]) continue; // ignore empty strings
|
||||
namespaces = split[i].replace(/\*/g, '.*?');
|
||||
if (namespaces[0] === '-') {
|
||||
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
||||
} else {
|
||||
exports.names.push(new RegExp('^' + namespaces + '$'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable debug output.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function disable() {
|
||||
exports.enable('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given mode name is enabled, false otherwise.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function enabled(name) {
|
||||
var i, len;
|
||||
for (i = 0, len = exports.skips.length; i < len; i++) {
|
||||
if (exports.skips[i].test(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (i = 0, len = exports.names.length; i < len; i++) {
|
||||
if (exports.names[i].test(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Coerce `val`.
|
||||
*
|
||||
* @param {Mixed} val
|
||||
* @return {Mixed}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function coerce(val) {
|
||||
if (val instanceof Error) return val.stack || val.message;
|
||||
return val;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* Detect Electron renderer process, which is node, but we should
|
||||
* treat as a browser.
|
||||
*/
|
||||
|
||||
if (typeof process !== 'undefined' && process.type === 'renderer') {
|
||||
module.exports = require('./browser.js');
|
||||
} else {
|
||||
module.exports = require('./node.js');
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var tty = require('tty');
|
||||
var util = require('util');
|
||||
|
||||
/**
|
||||
* This is the Node.js implementation of `debug()`.
|
||||
*
|
||||
* Expose `debug()` as the module.
|
||||
*/
|
||||
|
||||
exports = module.exports = require('./debug');
|
||||
exports.init = init;
|
||||
exports.log = log;
|
||||
exports.formatArgs = formatArgs;
|
||||
exports.save = save;
|
||||
exports.load = load;
|
||||
exports.useColors = useColors;
|
||||
|
||||
/**
|
||||
* Colors.
|
||||
*/
|
||||
|
||||
exports.colors = [6, 2, 3, 4, 5, 1];
|
||||
|
||||
/**
|
||||
* Build up the default `inspectOpts` object from the environment variables.
|
||||
*
|
||||
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
||||
*/
|
||||
|
||||
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
|
||||
return /^debug_/i.test(key);
|
||||
}).reduce(function (obj, key) {
|
||||
// camel-case
|
||||
var prop = key
|
||||
.substring(6)
|
||||
.toLowerCase()
|
||||
.replace(/_([a-z])/, function (_, k) { return k.toUpperCase() });
|
||||
|
||||
// coerce string value into JS value
|
||||
var val = process.env[key];
|
||||
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
|
||||
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
|
||||
else if (val === 'null') val = null;
|
||||
else val = Number(val);
|
||||
|
||||
obj[prop] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
/**
|
||||
* The file descriptor to write the `debug()` calls to.
|
||||
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
|
||||
*
|
||||
* $ DEBUG_FD=3 node script.js 3>debug.log
|
||||
*/
|
||||
|
||||
if ('DEBUG_FD' in process.env) {
|
||||
util.deprecate(function(){}, '`DEBUG_FD` is deprecated. Override `debug.log` if you want to use a different log function (https://git.io/vMUyr)')()
|
||||
}
|
||||
|
||||
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
|
||||
var stream = 1 === fd ? process.stdout :
|
||||
2 === fd ? process.stderr :
|
||||
createWritableStdioStream(fd);
|
||||
|
||||
/**
|
||||
* Is stdout a TTY? Colored output is enabled when `true`.
|
||||
*/
|
||||
|
||||
function useColors() {
|
||||
return 'colors' in exports.inspectOpts
|
||||
? Boolean(exports.inspectOpts.colors)
|
||||
: tty.isatty(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map %o to `util.inspect()`, all on a single line.
|
||||
*/
|
||||
|
||||
exports.formatters.o = function(v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts)
|
||||
.replace(/\s*\n\s*/g, ' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Map %o to `util.inspect()`, allowing multiple lines if needed.
|
||||
*/
|
||||
|
||||
exports.formatters.O = function(v) {
|
||||
this.inspectOpts.colors = this.useColors;
|
||||
return util.inspect(v, this.inspectOpts);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds ANSI color escape codes if enabled.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function formatArgs(args) {
|
||||
var name = this.namespace;
|
||||
var useColors = this.useColors;
|
||||
|
||||
if (useColors) {
|
||||
var c = this.color;
|
||||
var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
|
||||
|
||||
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
||||
args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
|
||||
} else {
|
||||
args[0] = new Date().toUTCString()
|
||||
+ ' ' + name + ' ' + args[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes `util.format()` with the specified arguments and writes to `stream`.
|
||||
*/
|
||||
|
||||
function log() {
|
||||
return stream.write(util.format.apply(util, arguments) + '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save `namespaces`.
|
||||
*
|
||||
* @param {String} namespaces
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function save(namespaces) {
|
||||
if (null == namespaces) {
|
||||
// If you set a process.env field to null or undefined, it gets cast to the
|
||||
// string 'null' or 'undefined'. Just delete instead.
|
||||
delete process.env.DEBUG;
|
||||
} else {
|
||||
process.env.DEBUG = namespaces;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load `namespaces`.
|
||||
*
|
||||
* @return {String} returns the previously persisted debug modes
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function load() {
|
||||
return process.env.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from `node/src/node.js`.
|
||||
*
|
||||
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also
|
||||
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
|
||||
*/
|
||||
|
||||
function createWritableStdioStream (fd) {
|
||||
var stream;
|
||||
var tty_wrap = process.binding('tty_wrap');
|
||||
|
||||
// Note stream._type is used for test-module-load-list.js
|
||||
|
||||
switch (tty_wrap.guessHandleType(fd)) {
|
||||
case 'TTY':
|
||||
stream = new tty.WriteStream(fd);
|
||||
stream._type = 'tty';
|
||||
|
||||
// Hack to have stream not keep the event loop alive.
|
||||
// See https://github.com/joyent/node/issues/1726
|
||||
if (stream._handle && stream._handle.unref) {
|
||||
stream._handle.unref();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'FILE':
|
||||
var fs = require('fs');
|
||||
stream = new fs.SyncWriteStream(fd, { autoClose: false });
|
||||
stream._type = 'fs';
|
||||
break;
|
||||
|
||||
case 'PIPE':
|
||||
case 'TCP':
|
||||
var net = require('net');
|
||||
stream = new net.Socket({
|
||||
fd: fd,
|
||||
readable: false,
|
||||
writable: true
|
||||
});
|
||||
|
||||
// FIXME Should probably have an option in net.Socket to create a
|
||||
// stream from an existing fd which is writable only. But for now
|
||||
// we'll just add this hack and set the `readable` member to false.
|
||||
// Test: ./node test/fixtures/echo.js < /etc/passwd
|
||||
stream.readable = false;
|
||||
stream.read = null;
|
||||
stream._type = 'pipe';
|
||||
|
||||
// FIXME Hack to have stream not keep the event loop alive.
|
||||
// See https://github.com/joyent/node/issues/1726
|
||||
if (stream._handle && stream._handle.unref) {
|
||||
stream._handle.unref();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Probably an error on in uv_guess_handle()
|
||||
throw new Error('Implement me. Unknown stream file type!');
|
||||
}
|
||||
|
||||
// For supporting legacy API we put the FD here.
|
||||
stream.fd = fd;
|
||||
|
||||
stream._isStdio = true;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init logic for `debug` instances.
|
||||
*
|
||||
* Create a new `inspectOpts` object in case `useColors` is set
|
||||
* differently for a particular `debug` instance.
|
||||
*/
|
||||
|
||||
function init (debug) {
|
||||
debug.inspectOpts = util._extend({}, exports.inspectOpts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable namespaces listed in `process.env.DEBUG` initially.
|
||||
*/
|
||||
|
||||
exports.enable(load());
|
|
@ -0,0 +1 @@
|
|||
test/fixtures/*.js
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"rules" : {
|
||||
"brace-style": [2, "stroustrup", { "allowSingleLine": true }],
|
||||
"camelcase": [0],
|
||||
"curly": [2],
|
||||
"eqeqeq": [2],
|
||||
"indent": [2, 2, {"SwitchCase": 1}],
|
||||
"max-len": [2, 120, 4, {"ignoreComments": true, "ignoreUrls": true}],
|
||||
"no-console": [1],
|
||||
"no-shadow": [1],
|
||||
"no-trailing-spaces": [2],
|
||||
"quotes": [2, "single"],
|
||||
"semi": [2, "always"],
|
||||
"space-after-keywords": [2, "always"],
|
||||
"space-before-blocks": [2],
|
||||
"space-infix-ops": [2],
|
||||
"space-unary-ops": [2]
|
||||
},
|
||||
"extends": "eslint:recommended"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
|
||||
private/
|
||||
*.log
|
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
sudo: false
|
||||
node_js:
|
||||
- "4.1"
|
|
@ -0,0 +1,19 @@
|
|||
Copyright 2014-2016 Peter Magnusson <peter@birchroad.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the 'Software'), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE
|
|
@ -0,0 +1,49 @@
|
|||
mdns-js-packet
|
||||
==============
|
||||
|
||||
[![Build Status](https://travis-ci.org/mdns-js/node-dns-js.svg?branch=master)](https://travis-ci.org/mdns-js/node-dns-js)
|
||||
|
||||
DNS packet parser specifically built for mdns-js
|
||||
[mdns-js](https://github.com/kmpm/node-mdns-js)
|
||||
but it should be generic enough to do general dns stuff.
|
||||
|
||||
NEW LOCATION
|
||||
|
||||
This project was moved into it's own organisation. Please update any git remotes you might have pointing here.
|
||||
|
||||
git remote set-url origin https://github.com/mdns-js/node-dns-js.git
|
||||
|
||||
|
||||
|
||||
You probably want to have a look at
|
||||
[native-dns-packet](https://github.com/tjfontaine/native-dns-packet)
|
||||
first and if that does do what you need, you might start looking at this.
|
||||
|
||||
mdns-js-packet should produce the same output as native-dns-packet,
|
||||
it even uses it's test fixtures and borrows some parts of it.
|
||||
|
||||
This was made before i knew about native-dns-packet but since that
|
||||
still has some bugs in handling some mDNS packets I cant use it.
|
||||
|
||||
example
|
||||
-------
|
||||
|
||||
```javascript
|
||||
var dns = require('dns-js');
|
||||
|
||||
/*some code that will get you a dns message buffer*/
|
||||
|
||||
var result = dns.DNSPacket.parse(message);
|
||||
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
Look at examples/dnsresolver.js for a more detailed example.
|
||||
|
||||
Contribute
|
||||
----------
|
||||
I will gladly accept any contributions as pull requests.
|
||||
Just run __npm run lint__ on the code first so that the coding style
|
||||
is kept somewhat consistent.
|
||||
I miss doing this myself from time to time and I won't go ballistic if anyone
|
||||
else forget but I would really appreciate it.
|
|
@ -0,0 +1,49 @@
|
|||
EDNS
|
||||
====
|
||||
Extension Mechanisms for DNS
|
||||
|
||||
This document will give some hints to litterature about edns
|
||||
and how it's done in this project.
|
||||
|
||||
* https://tools.ietf.org/html/rfc6891
|
||||
* https://en.wikipedia.org/wiki/Extension_mechanisms_for_DNS
|
||||
|
||||
|
||||
|
||||
OPT RR, 41/0x29
|
||||
---------------
|
||||
OPT RR MAY be placed anywhere in the additional data section,
|
||||
it MUST be the only OPT RR in that message.
|
||||
|
||||
###Wireformat
|
||||
Wireformat is described in section 6.1.2 of RFC6891
|
||||
|
||||
Fixed part
|
||||
```
|
||||
+------------+--------------+------------------------------+
|
||||
| Field Name | Field Type | Description |
|
||||
+------------+--------------+------------------------------+
|
||||
| NAME | domain name | MUST be 0 (root domain) |
|
||||
| TYPE | u_int16_t | OPT (41) |
|
||||
| CLASS | u_int16_t | requestor's UDP payload size |
|
||||
| TTL | u_int32_t | extended RCODE and flags |
|
||||
| RDLEN | u_int16_t | length of all RDATA |
|
||||
| RDATA | octet stream | {attribute,value} pairs |
|
||||
+------------+--------------+------------------------------+
|
||||
```
|
||||
|
||||
Varable part
|
||||
```
|
||||
+0 (MSB) +1 (LSB)
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
0: | OPTION-CODE |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
2: | OPTION-LENGTH |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
4: | |
|
||||
/ OPTION-DATA /
|
||||
/ /
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
RCODE
|
||||
=====
|
||||
|
||||
http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
|
||||
|
||||
|rcode | Name | Description | Reference |
|
||||
|------------|------------|--------------------------------------|-----------------------|
|
||||
| 0 | NoError | No Error | [RFC1035] |
|
||||
| 1 | FormErr | Format Error | [RFC1035] |
|
||||
| 2 | ServFail | Server Failure | [RFC1035] |
|
||||
| 3 | NXDomain | Non-Existent Domain | [RFC1035] |
|
||||
| 4 | NotImp | Not Implemented | [RFC1035] |
|
||||
| 5 | Refused | Query Refused | [RFC1035] |
|
||||
| 6 | YXDomain | Name Exists when it should not | [RFC2136][RFC6672] |
|
||||
| 7 | YXRRSet | RR Set Exists when it should not | [RFC2136] |
|
||||
| 8 | NXRRSet | RR Set that should exist does not | [RFC2136] |
|
||||
| 9 | NotAuth | Server Not Authoritative for zone | [RFC2136] |
|
||||
| 9 | NotAuth | Not Authorized | [RFC2845] |
|
||||
| 10 | NotZone | Name not contained in zone | [RFC2136] |
|
||||
| 11-15 | Unassigned | | |
|
||||
| 16 | BADVERS | Bad OPT Version | [RFC6891] |
|
||||
| 16 | BADSIG | TSIG Signature Failure | [RFC2845] |
|
||||
| 17 | BADKEY | Key not recognized | [RFC2845] |
|
||||
| 18 | BADTIME | Signature out of time window | [RFC2845] |
|
||||
| 19 | BADMODE | Bad TKEY Mode | [RFC2930] |
|
||||
| 20 | BADNAME | Duplicate key name | [RFC2930] |
|
||||
| 21 | BADALG | Algorithm not supported | [RFC2930] |
|
||||
| 22 | BADTRUNC | Bad Truncation | [RFC4635] |
|
||||
| 23 | BADCOOKIE | Bad/missing server cookie* | |
|
||||
| 24-3840 | Unassigned | | |
|
||||
| 3841-4095 | Reserved | for Private Use | [RFC6895] |
|
||||
| 4096-65534 | Unassigned | | |
|
||||
| 65535 | Reserved | can be allocated by Standards Action | [RFC6895] |
|
||||
------------------------------------------------------------------------------------------
|
||||
*TEMPORARY - registered 2015-07-26, expires 2016-07-26 [draft-ietf-dnsop-cookies]
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
Record types
|
||||
============
|
||||
|
||||
A usefull list of record types can be found at
|
||||
https://en.wikipedia.org/wiki/List_of_DNS_record_types
|
||||
|
||||
A - 1
|
||||
-----
|
||||
```
|
||||
{ name: 'TV i Vardagsrummet.local',
|
||||
type: 1,
|
||||
class: 32769,
|
||||
ttl: 120,
|
||||
address: '192.168.1.89' }
|
||||
```
|
||||
|
||||
|
||||
PTR - 12
|
||||
--------
|
||||
```
|
||||
{ name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 4500,
|
||||
data: 'TV i Vardagsrummet._googlecast._tcp.local' }
|
||||
|
||||
```
|
||||
|
||||
|
||||
SRV - 33
|
||||
--------
|
||||
```
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 32769,
|
||||
ttl: 120,
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 8009,
|
||||
target: 'TV i Vardagsrummet.local' }
|
||||
```
|
||||
|
||||
|
||||
TXT - 16
|
||||
-------
|
||||
{ name: 'SkC$rm i GC$strummet._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 32769,
|
||||
ttl: 4500,
|
||||
data:
|
||||
[ 'id=c3cccef1d09583a377f9613567168f71',
|
||||
've=02',
|
||||
'md=Chromecast',
|
||||
'ic=/setup/icon.png',
|
||||
'fn=SkC$rm i GC$strummet',
|
||||
'ca=5',
|
||||
'st=0' ] }
|
|
@ -0,0 +1,47 @@
|
|||
/*eslint no-console:0*/
|
||||
var dns = require('..');
|
||||
var dgram = require('dgram');
|
||||
|
||||
var DNSSERVER = '8.8.8.8';
|
||||
|
||||
resolveAddress('www.google.com');
|
||||
|
||||
function resolveAddress(name) {
|
||||
var packet = new dns.DNSPacket();
|
||||
packet.header.rd = 1; //make query recursive
|
||||
packet.question.push(new dns.DNSRecord(
|
||||
name,
|
||||
dns.DNSRecord.Type.A, 1)
|
||||
);
|
||||
|
||||
var s = dgram.createSocket('udp4');
|
||||
s.bind();
|
||||
|
||||
s.on('listening', function () {
|
||||
var buf = dns.DNSPacket.toBuffer(packet);
|
||||
s.send(buf, 0, buf.length, 53, DNSSERVER, function (err, bytes) {
|
||||
if (err) {
|
||||
return console.error('error sending', err);
|
||||
}
|
||||
console.log('sent request of %d bytes', bytes);
|
||||
});
|
||||
});
|
||||
|
||||
s.on('message', function (data) {
|
||||
console.log('incoming response');
|
||||
var response = dns.DNSPacket.parse(data);
|
||||
response.answer.forEach(function (a) {
|
||||
console.log('answer type:%s, class:%s, name:%s',
|
||||
a.typeName, a.className, a.name, a.address);
|
||||
});
|
||||
s.close();
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log('connection closed');
|
||||
});
|
||||
|
||||
s.on('error', function (err) {
|
||||
console.error('error', err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*eslint no-console:0*/
|
||||
var dns = require('..');
|
||||
var dgram = require('dgram');
|
||||
|
||||
var DNSSERVER = '8.8.8.8';
|
||||
|
||||
resolveName('140.211.167.51');
|
||||
|
||||
function resolveName(address) {
|
||||
var packet = new dns.DNSPacket();
|
||||
packet.header.rd = 1; //make query recursive
|
||||
packet.header.id = 4242;
|
||||
var qname = address.split('.').reverse().join('.') + '.in-addr.arpa.';
|
||||
console.log('qname', qname);
|
||||
packet.question.push(new dns.DNSRecord(
|
||||
qname,
|
||||
dns.DNSRecord.Type.PTR, 1)
|
||||
);
|
||||
|
||||
var s = dgram.createSocket('udp4');
|
||||
s.bind();
|
||||
|
||||
s.on('listening', function () {
|
||||
var buf = dns.DNSPacket.toBuffer(packet);
|
||||
s.send(buf, 0, buf.length, 53, DNSSERVER, function (err, bytes) {
|
||||
if (err) {
|
||||
return console.error('error sending', err);
|
||||
}
|
||||
console.log('sent request of %d bytes', bytes);
|
||||
});
|
||||
});
|
||||
|
||||
s.on('message', function (data) {
|
||||
console.log('incoming response');
|
||||
|
||||
var response = dns.DNSPacket.parse(data);
|
||||
if (response.header.rcode === 0) {
|
||||
response.answer.forEach(function (a) {
|
||||
console.log('answer type:%s, class:%s, name:%s, data: %s',
|
||||
a.typeName, a.className, a.name, a.data);
|
||||
console.log('IP %s have resolved to name %s', address, a.data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.log('Server responded with error');
|
||||
if (response.header.rcode === dns.DNSPacket.RCODE.NXDomain) {
|
||||
console.log('No such name');
|
||||
}
|
||||
else {
|
||||
console.log('rcode', response.header.rcode);
|
||||
}
|
||||
}
|
||||
|
||||
s.close();
|
||||
});
|
||||
|
||||
s.on('end', function () {
|
||||
console.log('connection closed');
|
||||
});
|
||||
|
||||
s.on('error', function (err) {
|
||||
console.error('error', err);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
module.exports = require('./lib');
|
Binary file not shown.
|
@ -0,0 +1,169 @@
|
|||
/* global Buffer */
|
||||
var debug = require('debug')('mdns-packet:lib:dns:bufferconsumer');
|
||||
var util = require('util');
|
||||
|
||||
var LABEL_POINTER = 0xc0;
|
||||
|
||||
var BufferConsumer = module.exports = function BufferConsumer(arg) {
|
||||
if (!(arg instanceof Buffer)) {
|
||||
debug('arg', arg);
|
||||
throw new Error('Expected instance of Buffer');
|
||||
}
|
||||
this.buffer = arg;
|
||||
this.length = this.buffer.length;
|
||||
debug('new consumer of %d bytes', this.length);
|
||||
this._offset = 0;
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.tell = function () {
|
||||
return this._offset;
|
||||
};
|
||||
|
||||
|
||||
BufferConsumer.prototype.seek = function (pos) {
|
||||
debug('seek(%d)', pos);
|
||||
if (pos < 0) {
|
||||
throw new Error('Negative pos not allowed');
|
||||
}
|
||||
if (pos > this.length) {
|
||||
debug('bad packet', this.buffer.toString('hex'));
|
||||
throw new Error(util.format('Cannot seek after EOF. %d > %d',
|
||||
pos, this.length));
|
||||
}
|
||||
this._offset = pos;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.slice = function (length) {
|
||||
var v;
|
||||
if (typeof length === 'undefined') {
|
||||
v = this.buffer.slice(this._offset);
|
||||
this._offset = this.length - 1;
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
if ((this._offset + length) > this.length) {
|
||||
debug('Buffer owerflow. Slice beyond buffer.', {
|
||||
offset: this._offset,
|
||||
length: length,
|
||||
bufferLength: this.length
|
||||
});
|
||||
debug('so far', this);
|
||||
throw new Error('Buffer overflow');
|
||||
}
|
||||
v = this.buffer.slice(this._offset, this._offset + length);
|
||||
this._offset += length;
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BufferConsumer.prototype.isEOF = function () {
|
||||
return this._offset >= this.length;
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.byte = function () {
|
||||
this._offset += 1;
|
||||
return this.buffer.readUInt8(this._offset - 1);
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.short = function () {
|
||||
debug('reading short at %d of %d', this._offset, this.length);
|
||||
this._offset += 2;
|
||||
return this.buffer.readUInt16BE(this._offset - 2);
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.long = function () {
|
||||
this._offset += 4;
|
||||
return this.buffer.readUInt32BE(this._offset - 4);
|
||||
};
|
||||
|
||||
BufferConsumer.prototype.string = function (encoding, length) {
|
||||
var end;
|
||||
var ret;
|
||||
|
||||
if (length === undefined) {
|
||||
end = this.buffer.length;
|
||||
}
|
||||
else {
|
||||
end = this.tell() + length;
|
||||
// if (end > this.length) {
|
||||
// throw new errors.MalformedPacket(
|
||||
// 'Trying to read past eof. Start=%d, End=%s, Length=%s',
|
||||
// this.tell(), end, this.length);
|
||||
// }
|
||||
}
|
||||
|
||||
if (!encoding) {
|
||||
encoding = 'utf8';
|
||||
}
|
||||
ret = this.buffer.toString(encoding, this._offset, end);
|
||||
debug('got a %s character string:', length, ret);
|
||||
this.seek(end);
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Consumes a DNS name, which will either finish with a NULL byte or a suffix
|
||||
* reference (i.e., 0xc0 <ref>).
|
||||
*/
|
||||
BufferConsumer.prototype.name = function (join, endAt) {
|
||||
debug('.name(join:%s, endAt:%s)', join, endAt);
|
||||
if (typeof join === 'undefined') { join = true; }
|
||||
var parts = [];
|
||||
var ret;
|
||||
var len;
|
||||
var pos;
|
||||
var end;
|
||||
var comp = false;
|
||||
len = this.byte();
|
||||
debug('name initial len', len);
|
||||
if (len === 0) {
|
||||
parts.push('');
|
||||
}
|
||||
while (len !== 0) {
|
||||
if ((len & LABEL_POINTER) === LABEL_POINTER) {
|
||||
debug('has label');
|
||||
len -= LABEL_POINTER;
|
||||
len = len << 8;
|
||||
pos = len + this.byte();
|
||||
if (!comp) {
|
||||
end = this.tell();
|
||||
}
|
||||
this.seek(pos);
|
||||
len = this.byte();
|
||||
comp = true;
|
||||
continue;
|
||||
}
|
||||
debug('no label');
|
||||
|
||||
// Otherwise, consume a string!
|
||||
var v = this.string('utf8', len);
|
||||
if (v.length > 0) {
|
||||
parts.push(v);
|
||||
}
|
||||
|
||||
if (endAt && this.tell() >= endAt) {
|
||||
debug('leaving at', endAt);
|
||||
break;
|
||||
}
|
||||
len = this.byte();
|
||||
debug('got len', len);
|
||||
}
|
||||
if (!comp) {
|
||||
end = this.tell();
|
||||
}
|
||||
debug('ended with %d parts at %d', parts.length, end);
|
||||
this.seek(end);
|
||||
if (join) {
|
||||
ret = parts.join('.');
|
||||
}
|
||||
else {
|
||||
ret = parts;
|
||||
}
|
||||
debug('ret', ret);
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
var debug = require('debug')('mdns-packet:lib:dns:bufferwriter');
|
||||
var util = require('util');
|
||||
var Qap = require('qap');
|
||||
|
||||
var BufferConsumer = require('./bufferconsumer');
|
||||
var BufferWriter = module.exports = function (size) {
|
||||
this.buf = new Buffer(size || 512);
|
||||
this.buf.fill(0);
|
||||
this.offset = 0;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.tell = function () {
|
||||
return this.offset;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.buffer = function (v) {
|
||||
if (typeof v === 'undefined') {
|
||||
return this;
|
||||
}
|
||||
if (v instanceof BufferWriter) {
|
||||
v = v.dump();
|
||||
}
|
||||
if (!(v instanceof Buffer)) {
|
||||
throw new Error('VariableError: not a buffer');
|
||||
}
|
||||
if (v.length > 0) {
|
||||
v.copy(this.buf, this.offset);
|
||||
this.offset += v.length;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
//4 bytes
|
||||
BufferWriter.prototype.long = function (v) {
|
||||
this.buf.writeInt32BE(v, this.offset);
|
||||
this.offset += 4;
|
||||
return this;
|
||||
};
|
||||
|
||||
//two bytes
|
||||
BufferWriter.prototype.short = function (v) {
|
||||
this.buf.writeUInt16BE(v & 0xFFFF, this.offset);
|
||||
this.offset += 2;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.seek = function (pos) {
|
||||
debug('seek(%d)', pos);
|
||||
if (pos < 0) {
|
||||
throw new Error('Negative pos not allowed');
|
||||
}
|
||||
if (pos > this.buf.length) {
|
||||
debug('bad packet', this.buffer.toString('hex'));
|
||||
throw new Error(util.format('Cannot seek after EOF. %d > %d',
|
||||
pos, this.buf.length));
|
||||
}
|
||||
this.offset = pos;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.byte = function (v) {
|
||||
this.buf.writeUInt8(v, this.offset);
|
||||
this.offset += 1;
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.slice = function (start, end) {
|
||||
return this.buf.slice(start, end);
|
||||
};
|
||||
|
||||
BufferWriter.prototype.indexOf = function (text) {
|
||||
var qap = new Qap(text);
|
||||
return qap.parse(this.buf);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a DNS name. If ref is specified, will finish this name with a
|
||||
* suffix reference (i.e., 0xc0 <ref>). If not, then will terminate with a NULL
|
||||
* byte.
|
||||
*/
|
||||
BufferWriter.prototype.name = function (v) {
|
||||
var self = this;
|
||||
debug('#name', v);
|
||||
var ref;
|
||||
var i;
|
||||
var j;
|
||||
var part;
|
||||
var parts = v.split('.');
|
||||
var parts2 = v.split('.');
|
||||
var consumer = new BufferConsumer(self.buf);
|
||||
var qap = new Qap('');
|
||||
var lastPart = parts.length;
|
||||
if (v.length > 0) {
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
if (parts[i].length === 0) {
|
||||
lastPart = i;
|
||||
continue;
|
||||
}
|
||||
part = new Buffer(parts[i]);
|
||||
qap.set(Buffer.concat([ new Buffer([ part.length ]), part ]));
|
||||
var location = qap.parse(self.buf)[0];
|
||||
if (location) {
|
||||
var tr = consumer.seek(location).name();
|
||||
if (tr === parts2.join('.')) {
|
||||
debug('found index: %s, from %s at %d', i, tr, location);
|
||||
ref = location;
|
||||
lastPart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
parts2.shift();
|
||||
}
|
||||
}
|
||||
var out = new BufferWriter();
|
||||
debug('lastPart', lastPart, parts);
|
||||
for (i = 0; i < lastPart; i++) {
|
||||
part = new Buffer(parts[i]);
|
||||
debug('writing part', part);
|
||||
out.byte(part.length);
|
||||
for (j = 0; j < part.length; ++j) {
|
||||
out.byte(part[j]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ref) {
|
||||
debug('writing a name ref to %d', ref);
|
||||
out.byte(0xc0).byte(ref);
|
||||
}
|
||||
else {
|
||||
out.byte(0);
|
||||
}
|
||||
this.buffer(out);
|
||||
return this;
|
||||
};
|
||||
|
||||
BufferWriter.prototype.dump = function () {
|
||||
return this.slice(0, this.tell());
|
||||
};
|
|
@ -0,0 +1,260 @@
|
|||
var debug = require('debug')('mdns-packet:lib:dns:dnspacket');
|
||||
var BufferWriter = require('./bufferwriter');
|
||||
var DataConsumer = require('./bufferconsumer');
|
||||
var DNSRecord = require('./dnsrecord');
|
||||
var errors = require('./errors');
|
||||
|
||||
var MIN_RECORD_SIZE = 5;
|
||||
/**
|
||||
* This callback is used for "each" methods
|
||||
* @callback DNSPacket~eachCallback
|
||||
* @param {DNSRecord} rec - DNSRecord that was found
|
||||
*/
|
||||
|
||||
var SECTION_NAMES = [
|
||||
'answer',
|
||||
'authority',
|
||||
'additional'
|
||||
];
|
||||
var ALL_SECTION_NAMES = ['question'].concat(SECTION_NAMES);
|
||||
|
||||
function parseFlags(val, packet) {
|
||||
packet.header.qr = (val & 0x8000) >> 15;
|
||||
packet.header.opcode = (val & 0x7800) >> 11;
|
||||
packet.header.aa = (val & 0x400) >> 10;
|
||||
packet.header.tc = (val & 0x200) >> 9;
|
||||
packet.header.rd = (val & 0x100) >> 8;
|
||||
packet.header.ra = (val & 0x80) >> 7;
|
||||
packet.header.res1 = (val & 0x40) >> 6;
|
||||
packet.header.res2 = (val & 0x20) >> 5;
|
||||
packet.header.res3 = (val & 0x10) >> 4;
|
||||
packet.header.rcode = (val & 0xF);
|
||||
}
|
||||
|
||||
function parseHeader(consumer, packet) {
|
||||
packet.header.id = consumer.short();
|
||||
parseFlags(consumer.short(), packet);
|
||||
|
||||
packet.question = new Array(consumer.short());
|
||||
packet.answer = new Array(consumer.short());
|
||||
packet.authority = new Array(consumer.short());
|
||||
packet.additional = new Array(consumer.short());
|
||||
debug('packet.header:', packet.header);
|
||||
debug('question: %d, answer: %d, authority: %d, additional: %d',
|
||||
packet.question.length, packet.answer.length, packet.authority.length,
|
||||
packet.additional.length);
|
||||
var allcount = packet.question.length + packet.answer.length +
|
||||
packet.authority.length + packet.additional.length;
|
||||
// allcount * MIN_RECORD_SIZE should be less then consumer.length - consumer.tell()
|
||||
if (allcount * MIN_RECORD_SIZE > (consumer.length - consumer.tell())) {
|
||||
throw new errors.MalformedPacket(
|
||||
'Unexpectedly big section count: %d. Missing at least %d bytes.',
|
||||
allcount,
|
||||
allcount * MIN_RECORD_SIZE - (consumer.length - consumer.tell()));
|
||||
}
|
||||
}
|
||||
|
||||
function writeHeader(writer, packet) {
|
||||
var header = packet.header;
|
||||
writer.short(header.id);
|
||||
var val = 0;
|
||||
val += (header.qr << 15) & 0x8000;
|
||||
val += (header.opcode << 11) & 0x7800;
|
||||
val += (header.aa << 10) & 0x400;
|
||||
val += (header.tc << 9) & 0x200;
|
||||
val += (header.rd << 8) & 0x100;
|
||||
val += (header.ra << 7) & 0x80;
|
||||
val += (header.res1 << 6) & 0x40;
|
||||
val += (header.res1 << 5) & 0x20;
|
||||
val += (header.res1 << 4) & 0x10;
|
||||
val += header.rcode & 0xF;
|
||||
writer.short(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* DNSPacket holds the state of a DNS packet. It can be modified or serialized
|
||||
* in-place.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
var DNSPacket = module.exports = function (flags) {
|
||||
|
||||
this.header = {
|
||||
id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 1,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0
|
||||
};
|
||||
if (flags) {
|
||||
parseFlags(flags, this);
|
||||
}
|
||||
this.question = [];
|
||||
this.answer = [];
|
||||
this.authority = [];
|
||||
this.additional = [];
|
||||
this.edns_options = [];
|
||||
this.payload = undefined;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum identifying DNSPacket flags
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
DNSPacket.Flag = {
|
||||
RESPONSE: 0x8000,
|
||||
AUTHORATIVE: 0x400,
|
||||
TRUNCATED: 0x200,
|
||||
RECURSION: 0x100
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enum identifying DNSPacket rcode flag values
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
DNSPacket.RCODE = {
|
||||
NoError: 0,
|
||||
FormErr: 1,
|
||||
ServFail: 2,
|
||||
NXDomain: 3
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse a DNSPacket from an Buffer
|
||||
* @param {Buffer} buffer - A Node.js Buffer instance
|
||||
* @returns {DNSPacket} Instance of DNSPacket
|
||||
*/
|
||||
DNSPacket.parse = function (buffer) {
|
||||
var consumer = new DataConsumer(buffer);
|
||||
var packet = new DNSPacket();
|
||||
var receivedOpts = 0;
|
||||
parseHeader(consumer, packet);
|
||||
|
||||
// Parse the QUESTION section.
|
||||
for (var qi = 0; qi < packet.question.length; qi++) {
|
||||
debug('doing qd %s', qi);
|
||||
try {
|
||||
debug('before question', consumer.tell());
|
||||
var part = DNSRecord.parseQuestion(consumer);
|
||||
packet.question[qi] = part;
|
||||
}
|
||||
catch (err) {
|
||||
debug('consumer', consumer);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the ANSWER, AUTHORITY and ADDITIONAL sections.
|
||||
SECTION_NAMES.forEach(function (sectionName) {
|
||||
var section = packet[sectionName];
|
||||
debug('about to parse section %s', sectionName, section.length);
|
||||
for (var si = 0; si < section.length; si++) {
|
||||
debug('doing record %s/%s', si + 1, section.length, consumer.tell());
|
||||
var record = DNSRecord.parse(consumer);
|
||||
debug('parsed type `%d` for section %s', record.type, sectionName);
|
||||
if (record.type === DNSRecord.Type.OPT) {
|
||||
if (receivedOpts++ >= 0) {
|
||||
//TODO: does it only ever be in additonal.
|
||||
if (sectionName === 'additional') {
|
||||
packet.edns_version = record.opt.version;
|
||||
packet.do = record.opt.do;
|
||||
packet.payload = record.class;
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug('more than 1 opts'. receivedOpts);
|
||||
}
|
||||
}
|
||||
section[si] = record;
|
||||
}
|
||||
});
|
||||
|
||||
if (!consumer.isEOF()) {
|
||||
debug('was not EOF on incoming packet. %d bytes in overflow',
|
||||
consumer.length - consumer.tell());
|
||||
var multiple = [packet];
|
||||
multiple.push(DNSPacket.parse(consumer.slice()));
|
||||
|
||||
return multiple;
|
||||
}
|
||||
debug('packet done', packet);
|
||||
return packet;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get records from packet
|
||||
* @param {DNSPacket.Section} section - record section [qd|an|ns|ar],
|
||||
* @param {DNSRecord.Type} [filter] - DNSRecord.Type to filter on
|
||||
* @param {DNSPacket~eachCallback} callback - Function callback
|
||||
*/
|
||||
DNSPacket.prototype.each = each;
|
||||
|
||||
|
||||
function each(section /*[,filter], callback*/) {
|
||||
if (ALL_SECTION_NAMES.indexOf(section) === -1) {
|
||||
throw new Error('Unkown section, ' + section);
|
||||
}
|
||||
var filter = false;
|
||||
var cb;
|
||||
if (arguments.length === 2) {
|
||||
cb = arguments[1];
|
||||
}
|
||||
else {
|
||||
filter = arguments[1];
|
||||
cb = arguments[2];
|
||||
if (typeof filter === 'undefined') {
|
||||
throw new Error('Filter given but is undefined');
|
||||
}
|
||||
}
|
||||
this[section].forEach(function (rec) {
|
||||
if (!filter || rec.type === filter) {
|
||||
cb(rec);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Serialize this DNSPacket into an Buffer for sending over UDP.
|
||||
* @returns {Buffer} A Node.js Buffer
|
||||
*/
|
||||
DNSPacket.toBuffer = function (packet) {
|
||||
var writer = new BufferWriter();
|
||||
var sections = ['question'].concat(SECTION_NAMES);
|
||||
writeHeader(writer, packet);
|
||||
|
||||
sections.forEach(function (sectionName) {
|
||||
var section = packet[sectionName];
|
||||
debug('%d records in %s', section.length, sectionName);
|
||||
writer.short(section.length);
|
||||
});
|
||||
|
||||
var e = each.bind(packet);
|
||||
|
||||
sections.forEach(function (sectionName) {
|
||||
e(sectionName, function (rec) {
|
||||
DNSRecord.write(writer, rec, true);
|
||||
|
||||
if (sectionName !== 'question' && rec.isQD) {
|
||||
throw new Error('unexpected QD record in non QD section.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return writer.slice(0, writer.tell());
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
var debug = require('debug')('mdns-packet:lib:dns:dnsrecord');
|
||||
|
||||
var BufferConsumer = require('./bufferconsumer');
|
||||
var errors = require('./errors');
|
||||
|
||||
/**
|
||||
* DNSRecord is a record inside a DNS packet; e.g. a QUESTION, or an ANSWER,
|
||||
* AUTHORITY, or ADDITIONAL record. Note that QUESTION records are special,
|
||||
* and do not have ttl or data.
|
||||
* @class
|
||||
* @param {string} name
|
||||
* @param {number} type
|
||||
* @param {number} cl - class
|
||||
* @param {number} [optTTL] - time to live in seconds
|
||||
*/
|
||||
var DNSRecord = module.exports = function (name, type, cl, optTTL) {
|
||||
var self = this;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.class = cl;
|
||||
|
||||
if (type === 0 || typeof type === 'undefined') {
|
||||
throw new errors.MalformedPacket('Record.type is empty');
|
||||
}
|
||||
|
||||
if (cl === 0) {
|
||||
throw new errors.MalformedPacket('Record.class is empty');
|
||||
}
|
||||
|
||||
this.ttl = (typeof optTTL !== 'undefined') ? optTTL : DNSRecord.TTL;
|
||||
this.isQD = (arguments.length === 3);
|
||||
debug('new DNSRecord', this);
|
||||
|
||||
|
||||
this.__defineGetter__('typeName', function () {
|
||||
return DNSRecord.TypeName[self.type];
|
||||
});
|
||||
|
||||
this.__defineGetter__('className', function () {
|
||||
return DNSRecord.ClassName[self.class & 0x7fff];
|
||||
});
|
||||
|
||||
this.__defineGetter__('flag', function () {
|
||||
return (self.class & 0x8000) >> 15;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum for record type values
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
DNSRecord.Type = {
|
||||
A: 0x01, // 1
|
||||
NS: 0x02, //2
|
||||
CNAME: 0x05, //5
|
||||
SOA: 0x06, //6
|
||||
PTR: 0x0c, // 12
|
||||
MX: 0x0f, //15
|
||||
TXT: 0x10, // 16
|
||||
AAAA: 28, // 0x16
|
||||
SRV: 0x21, // 33
|
||||
OPT: 0x29, //41 RFC6981 -needed for EDNS
|
||||
NSEC: 0x2f, //47
|
||||
TLSA: 0x34, //52 RFC6698 - associate TLS server certificate.
|
||||
ANY: 0xff
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum for record class values
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
DNSRecord.Class = {
|
||||
IN: 0x01,
|
||||
ANY: 0xff,
|
||||
FLUSH: 0x8000,
|
||||
IS_QM: 0x8000
|
||||
};
|
||||
|
||||
|
||||
DNSRecord.TTL = 3600; // one hour default TTL
|
||||
DNSRecord.TypeName = {};
|
||||
DNSRecord.ClassName = {};
|
||||
|
||||
var typekey;
|
||||
|
||||
for (typekey in DNSRecord.Type) {
|
||||
if (DNSRecord.Type.hasOwnProperty(typekey)) {
|
||||
DNSRecord.TypeName[DNSRecord.Type[typekey]] = typekey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (typekey in DNSRecord.Class) {
|
||||
if (DNSRecord.Class.hasOwnProperty(typekey)) {
|
||||
DNSRecord.ClassName[DNSRecord.Class[typekey]] = typekey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DNSRecord.write = function (out, rec, withLength) {
|
||||
withLength = withLength || false;
|
||||
debug('#write() type: %s, flag:%d class:%s, withLength:%s',
|
||||
rec.typeName, rec.flag,
|
||||
rec.className, withLength);
|
||||
if (rec.type === 0 || rec.class === 0) {
|
||||
throw new Error('Bad record with empty type and/or class');
|
||||
}
|
||||
//TODO:if outer and any string in data or name
|
||||
// can be found there. Do a ref instead.
|
||||
out.name(rec.name).short(rec.type).short(rec.class);
|
||||
if (rec.isQD) {
|
||||
return out;
|
||||
}
|
||||
|
||||
out.long(rec.ttl);
|
||||
|
||||
var startPos = out.tell();
|
||||
out.short(0xffff); //reserve some length
|
||||
|
||||
switch (rec.type) {
|
||||
case DNSRecord.Type.A:
|
||||
writeA(out, rec.address);
|
||||
break;
|
||||
case DNSRecord.Type.NS:
|
||||
case DNSRecord.Type.CNAME:
|
||||
case DNSRecord.Type.PTR:
|
||||
out.name(rec.data);
|
||||
break;
|
||||
case DNSRecord.Type.MX:
|
||||
//asMx(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.TXT:
|
||||
for (var key in rec.data) {
|
||||
if (rec.data.hasOwnProperty(key)) {
|
||||
// properly encode this
|
||||
out.name(key + '=' + rec.data[key]);
|
||||
out.offset--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DNSRecord.Type.AAAA:
|
||||
//asAAAA(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.SRV:
|
||||
out.short(rec.priority & 0xffff).short(rec.weight & 0xffff)
|
||||
.short(rec.port & 0xffff).name(rec.target);
|
||||
break;
|
||||
case DNSRecord.Type.SOA:
|
||||
out.name(rec.primary).name(rec.admin).long(rec.serial).long(rec.refresh)
|
||||
.long(rec.retry).long(rec.expiration).long(rec.minimum);
|
||||
break;
|
||||
default:
|
||||
debug('non implemented recordtype of ' + rec.type);
|
||||
throw new Error('Not implemented recordtype');
|
||||
//this.data = new BufferConsumer(consumer.slice(dataSize));
|
||||
}
|
||||
var endPos = out.tell();
|
||||
//update with correct size
|
||||
var correctSize = endPos - startPos - 2;
|
||||
debug('correct size=%s bytes', correctSize);
|
||||
out.seek(startPos).short(correctSize).seek(endPos);
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function writeA(out, ip) {
|
||||
var parts = ip.split('.');
|
||||
for (var i = 0; i < 4; i++) {
|
||||
out.byte(parts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
DNSRecord.parse = function (consumer) {
|
||||
if (consumer instanceof Buffer) {
|
||||
debug('making consumer out of buffer');
|
||||
consumer = new BufferConsumer(consumer);
|
||||
consumer.seek(0);
|
||||
}
|
||||
|
||||
debug('#parse from %d', consumer.tell());
|
||||
var rec = new DNSRecord(
|
||||
consumer.name(),
|
||||
consumer.short(), // type
|
||||
consumer.short(), // class
|
||||
consumer.long() //ttlgf
|
||||
);
|
||||
|
||||
debug('parsing from %d', consumer.tell());
|
||||
|
||||
var dataSize = consumer.short();
|
||||
debug('going for type %s. start: %d, size: %d, end: %d, length: %d',
|
||||
rec.type,
|
||||
consumer.tell(),
|
||||
dataSize,
|
||||
consumer.tell() + dataSize,
|
||||
consumer.length
|
||||
);
|
||||
|
||||
|
||||
switch (rec.type) {
|
||||
case DNSRecord.Type.A:
|
||||
asA(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.NS:
|
||||
case DNSRecord.Type.CNAME:
|
||||
case DNSRecord.Type.PTR:
|
||||
rec.data = asName(consumer);
|
||||
break;
|
||||
case DNSRecord.Type.MX:
|
||||
asMx(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.TXT:
|
||||
rec.data = asTxt(consumer, consumer.tell() + dataSize);
|
||||
break;
|
||||
case DNSRecord.Type.AAAA:
|
||||
asAAAA(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.SRV:
|
||||
asSrv(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.SOA:
|
||||
asSoa(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.OPT:
|
||||
asOpt(consumer, rec);
|
||||
break;
|
||||
case DNSRecord.Type.TLSA:
|
||||
asTLSA(consumer, rec, dataSize);
|
||||
break;
|
||||
default:
|
||||
debug('non implemented recordtype of ' + rec.type);
|
||||
rec.data = new BufferConsumer(consumer.slice(dataSize));
|
||||
}
|
||||
debug('record done at %d', consumer.tell(), rec);
|
||||
return rec;
|
||||
};
|
||||
|
||||
DNSRecord.parseQuestion = function (consumer) {
|
||||
if (consumer instanceof Buffer) {
|
||||
debug('making consumer out of buffer');
|
||||
consumer = new BufferConsumer(consumer);
|
||||
}
|
||||
debug('#parseQuestion from %d', consumer.tell());
|
||||
var r = new DNSRecord(
|
||||
consumer.name(),
|
||||
consumer.short(), // type
|
||||
consumer.short() // class
|
||||
);
|
||||
debug('record done at %d', consumer.tell(), r);
|
||||
return r;
|
||||
};
|
||||
|
||||
|
||||
function asName(consumer) {
|
||||
return consumer.name(true);
|
||||
}
|
||||
|
||||
|
||||
function asSrv(consumer, record) {
|
||||
debug('priority: %d', record.priority = consumer.short());
|
||||
debug('weight: %d', record.weight = consumer.short());
|
||||
debug('port: %d', record.port = consumer.short());
|
||||
record.target = consumer.name();
|
||||
// debug('priority:%d, weight: %d, port:%d, target:%s', record.priority,
|
||||
// record.weight, record.port, record.target);
|
||||
|
||||
}
|
||||
|
||||
function asMx(consumer, record) {
|
||||
record.priority = consumer.short();
|
||||
record.exchange = asName(consumer);
|
||||
}
|
||||
|
||||
function asTxt(consumer, endAt) {
|
||||
var items = consumer.name(false, endAt);
|
||||
debug('txt items', items);
|
||||
//note:disable to have same syntax as native-dns-packet
|
||||
// if (items.length === 1 && items[0].length > 0) {
|
||||
// return items[0];
|
||||
// }
|
||||
return items;
|
||||
}
|
||||
|
||||
|
||||
function asA(consumer, record) {
|
||||
var data = '';
|
||||
for (var i = 0; i < 3; i++) {
|
||||
data += consumer.byte() + '.';
|
||||
}
|
||||
data += consumer.byte();
|
||||
record.address = data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse data into a IPV6 address string
|
||||
* @returns {string}
|
||||
*/
|
||||
function asAAAA(consumer, packet) {
|
||||
var data = '';
|
||||
for (var i = 0; i < 7; i++) {
|
||||
data += consumer.short().toString(16) + ':';
|
||||
}
|
||||
data += consumer.short().toString(16);
|
||||
packet.address = data;
|
||||
}
|
||||
|
||||
function asSoa(consumer, packet) {
|
||||
packet.primary = consumer.name(true);
|
||||
packet.admin = consumer.name(true);
|
||||
packet.serial = consumer.long();
|
||||
packet.refresh = consumer.long();
|
||||
packet.retry = consumer.long();
|
||||
packet.expiration = consumer.long();
|
||||
packet.minimum = consumer.long();
|
||||
}
|
||||
|
||||
function asOpt(consumer, packet) {
|
||||
//if at end of buffer there is no optional data.
|
||||
var opt = {
|
||||
code: 0,
|
||||
data: [],
|
||||
rcode: 0,
|
||||
version: 0,
|
||||
do: 0,
|
||||
z: 0
|
||||
};
|
||||
|
||||
if (!consumer.isEOF()) {
|
||||
opt.code = consumer.short();
|
||||
opt.data = consumer.slice(consumer.short());
|
||||
}
|
||||
|
||||
opt.rcode = (packet.ttl & 0xff000000) >> 24;
|
||||
opt.version = (packet.ttl & 0x00FF0000) >> 16;
|
||||
opt.do = (packet.ttl & 0x00008000) >> 15;
|
||||
opt.z = (packet.ttl & 0x00001FFF);
|
||||
|
||||
debug('asOpt', opt);
|
||||
packet.opt = opt;
|
||||
}
|
||||
|
||||
function asTLSA(consumer, packet, dataSize) {
|
||||
packet.usage = consumer.byte();
|
||||
packet.selector = consumer.byte();
|
||||
packet.matchingtype = consumer.byte();
|
||||
packet.buff = consumer.slice(dataSize - 3); //size - 3 because of 3 bytes above
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
var util = require('util');
|
||||
|
||||
|
||||
function MalformedPacket(/*message*/) {
|
||||
Error.call(this);
|
||||
this.message = util.format.apply(null, arguments);
|
||||
}
|
||||
|
||||
util.inherits(MalformedPacket, Error);
|
||||
|
||||
module.exports.MalformedPacket = MalformedPacket;
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
|
||||
|
||||
exports.DNSPacket = require('./dnspacket');
|
||||
exports.DNSRecord = require('./dnsrecord');
|
||||
exports.errors = require('./errors');
|
||||
exports.parse = exports.DNSPacket.parse;
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"raw": "dns-js",
|
||||
"scope": null,
|
||||
"escapedName": "dns-js",
|
||||
"name": "dns-js",
|
||||
"rawSpec": "",
|
||||
"spec": "latest",
|
||||
"type": "tag"
|
||||
},
|
||||
"/srv/demos"
|
||||
]
|
||||
],
|
||||
"_from": "dns-js@latest",
|
||||
"_id": "dns-js@0.2.1",
|
||||
"_inCache": true,
|
||||
"_location": "/dns-js",
|
||||
"_nodeVersion": "4.2.2",
|
||||
"_npmUser": {
|
||||
"name": "kmpm",
|
||||
"email": "peter@birchroad.net"
|
||||
},
|
||||
"_npmVersion": "2.14.7",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"raw": "dns-js",
|
||||
"scope": null,
|
||||
"escapedName": "dns-js",
|
||||
"name": "dns-js",
|
||||
"rawSpec": "",
|
||||
"spec": "latest",
|
||||
"type": "tag"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/dns-js/-/dns-js-0.2.1.tgz",
|
||||
"_shasum": "5d66629b3c0e6a5eb0e14f0ae701d05f6ea46673",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "dns-js",
|
||||
"_where": "/srv/demos",
|
||||
"author": {
|
||||
"name": "Peter Magnusson",
|
||||
"email": "peter@birchroad.net"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/mdns-js/node-dns-js/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": "^2.1.0",
|
||||
"qap": "^3.1.2"
|
||||
},
|
||||
"description": "DNS Packet handling in pure javascript",
|
||||
"devDependencies": {
|
||||
"code": "*",
|
||||
"eslint": "*",
|
||||
"lab": "*",
|
||||
"native-dns-packet": "0.1.1"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "5d66629b3c0e6a5eb0e14f0ae701d05f6ea46673",
|
||||
"tarball": "https://registry.npmjs.org/dns-js/-/dns-js-0.2.1.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.1.0"
|
||||
},
|
||||
"gitHead": "ba92d56656a7671753153904bcba72458892b7d9",
|
||||
"homepage": "https://github.com/mdns-js/node-dns-js",
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "kmpm",
|
||||
"email": "peter@birchroad.net"
|
||||
}
|
||||
],
|
||||
"name": "dns-js",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mdns-js/node-dns-js.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "lab --coverage --flat"
|
||||
},
|
||||
"version": "0.2.1"
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
var Code = require('code'); // assertion library
|
||||
var Lab = require('lab');
|
||||
var lab = exports.lab = Lab.script();
|
||||
|
||||
var describe = lab.describe;
|
||||
var it = lab.it;
|
||||
//var before = lab.before;
|
||||
//var after = lab.after;
|
||||
var expect = Code.expect;
|
||||
|
||||
var BufferConsumer = require('../lib/bufferconsumer');
|
||||
var BufferWriter = require('../lib/bufferwriter');
|
||||
|
||||
|
||||
describe('BufferConsumer', function () {
|
||||
|
||||
it('throw if no buffer as argument', function (done) {
|
||||
var throws = function () {
|
||||
return (new BufferConsumer());
|
||||
};
|
||||
|
||||
expect(throws).to.throw(Error, 'Expected instance of Buffer');
|
||||
done();
|
||||
});
|
||||
|
||||
it('throw if seek before 0', function (done) {
|
||||
var throws = function () {
|
||||
var b = new Buffer(512);
|
||||
var consumer = new BufferConsumer(b);
|
||||
consumer.seek(-1);
|
||||
};
|
||||
|
||||
expect(throws).to.throw(Error, 'Negative pos not allowed');
|
||||
done();
|
||||
});
|
||||
|
||||
it('throw if seek after end', function (done) {
|
||||
var throws = function () {
|
||||
var b = new Buffer(512);
|
||||
var consumer = new BufferConsumer(b);
|
||||
consumer.seek(515);
|
||||
};
|
||||
|
||||
expect(throws).to.throw(Error, 'Cannot seek after EOF. 515 > 512');
|
||||
done();
|
||||
});
|
||||
|
||||
it('thow if slice after end', function (done) {
|
||||
var throws = function () {
|
||||
var b = new Buffer(512);
|
||||
var consumer = new BufferConsumer(b);
|
||||
consumer.seek(500);
|
||||
consumer.slice(100);
|
||||
};
|
||||
|
||||
expect(throws).to.throw(Error, 'Buffer overflow');
|
||||
done();
|
||||
});
|
||||
|
||||
it('#string with length', function (done) {
|
||||
var b = new Buffer('qwertasdfg');
|
||||
var consumer = new BufferConsumer(b);
|
||||
var s = consumer.string('utf8', 3);
|
||||
expect(s).to.equal('qwe');
|
||||
s = consumer.string();
|
||||
expect(s).to.equal('rtasdfg');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('BufferWriter', function () {
|
||||
it('#name on empty buffer', function (done) {
|
||||
var out = new BufferWriter();
|
||||
out.name('');
|
||||
out.dump();
|
||||
var consumer = new BufferConsumer(out.dump());
|
||||
var s = consumer.name();
|
||||
expect(s).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
Binary file not shown.
|
@ -0,0 +1,45 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '_googlecast._tcp.local', type: 12, class: 32769 },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 32769 },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 32769 },
|
||||
{ name: 'Skärm i Gästrummet._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 32769 },
|
||||
{ name: 'Skärm i Gästrummet._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 32769 },
|
||||
{ name: 'TV i Vardagsrummet.local', type: 1, class: 32769 },
|
||||
{ name: 'TV i Vardagsrummet.local', type: 28, class: 32769 },
|
||||
{ name: 'Skärm i Gästrummet.local', type: 1, class: 32769 },
|
||||
{ name: 'Skärm i Gästrummet.local', type: 28, class: 32769 } ],
|
||||
answer:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 2477,
|
||||
data: 'TV i Vardagsrummet._googlecast._tcp.local' },
|
||||
{ name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 2473,
|
||||
data: 'Skärm i Gästrummet._googlecast._tcp.local' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,26 @@
|
|||
{ header:
|
||||
{ id: 10918,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 1,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '8.8.8.8.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer: [],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,35 @@
|
|||
{ header:
|
||||
{ id: 10918,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 1,
|
||||
ra: 1,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '8.8.8.8.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer:
|
||||
[ { name: '8.8.8.8.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 21599,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: 'google-public-dns-a.google.com' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,41 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 1,
|
||||
ra: 1,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: 'www.google.com',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer: [],
|
||||
authority:
|
||||
[ { name: 'google.com',
|
||||
type: 6,
|
||||
class: 1,
|
||||
ttl: 59,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
primary: 'ns1.google.com',
|
||||
admin: 'dns-admin.google.com',
|
||||
serial: 1576192,
|
||||
refresh: 7200,
|
||||
retry: 1800,
|
||||
expiration: 1209600,
|
||||
minimum: 300 } ],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,41 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 1,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question: [],
|
||||
answer:
|
||||
[ { name: '_http._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
data: 'myserver._http._tcp.local' },
|
||||
{ name: 'myserver._http._tcp.local',
|
||||
type: 33,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 8080,
|
||||
target: 'myserver1.local' },
|
||||
{ name: 'myserver._http._tcp.local',
|
||||
type: 16,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
data: [ 'dept=deustotech', 'hello=world' ] },
|
||||
{ name: 'myserver1.local',
|
||||
type: 1,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
address: '127.0.0.1' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,72 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 1,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: 'Chromecast.Bedroom._googlecast._tcp.local' } ],
|
||||
authority: [],
|
||||
additional:
|
||||
[ { name: 'Chromecast.Bedroom._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 8009,
|
||||
target: 'Chromecast.local' },
|
||||
{ name: 'Chromecast.Bedroom._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data:
|
||||
[ 'id=39dc44f5af0f3dd4f370a392d5050f5d',
|
||||
've=02',
|
||||
'md=Chromecast',
|
||||
'ic=/setup/icon.png',
|
||||
'fn=Chromecast.Bedroom',
|
||||
'ca=5',
|
||||
'st=0' ] },
|
||||
{ name: 'Chromecast.local',
|
||||
type: 1,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
address: '192.168.1.222' } ],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,72 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 4498,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: 'TV i Vardagsrummet._googlecast._tcp.local' },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 32769,
|
||||
ttl: 118,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 8009,
|
||||
target: 'TV i Vardagsrummet.local' },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 32769,
|
||||
ttl: 4498,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data:
|
||||
[ 'id=f1fb463167bed5b5d903d22686ac338c',
|
||||
've=02',
|
||||
'md=Chromecast',
|
||||
'ic=/setup/icon.png',
|
||||
'fn=TV i Vardagsrummet',
|
||||
'ca=5',
|
||||
'st=0' ] },
|
||||
{ name: 'TV i Vardagsrummet.local',
|
||||
type: 1,
|
||||
class: 32769,
|
||||
ttl: 118,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
address: '192.168.1.89' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,85 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 1,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question: [],
|
||||
answer:
|
||||
[ { name: '_googlecast._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 4500,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: 'TV i Vardagsrummet._googlecast._tcp.local' } ],
|
||||
authority: [],
|
||||
additional:
|
||||
[ { name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 16,
|
||||
class: 32769,
|
||||
ttl: 4500,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data:
|
||||
[ 'id=f1fb463167bed5b5d903d22686ac338c',
|
||||
've=02',
|
||||
'md=Chromecast',
|
||||
'ic=/setup/icon.png',
|
||||
'fn=TV i Vardagsrummet',
|
||||
'ca=5',
|
||||
'st=0' ] },
|
||||
{ name: 'TV i Vardagsrummet.local',
|
||||
type: 1,
|
||||
class: 32769,
|
||||
ttl: 120,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
address: '192.168.1.89' },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 33,
|
||||
class: 32769,
|
||||
ttl: 120,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
priority: 0,
|
||||
weight: 0,
|
||||
port: 8009,
|
||||
target: 'TV i Vardagsrummet.local' },
|
||||
{ name: 'TV i Vardagsrummet._googlecast._tcp.local',
|
||||
type: 47,
|
||||
class: 32769,
|
||||
ttl: 4500,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data:
|
||||
{ buffer: <Buffer c0 2e 00 05 00 00 80 00 40>,
|
||||
length: 9,
|
||||
_offset: 0 } },
|
||||
{ name: 'TV i Vardagsrummet.local',
|
||||
type: 47,
|
||||
class: 32769,
|
||||
ttl: 120,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: { buffer: <Buffer c0 ba 00 01 40>, length: 5, _offset: 0 } } ],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,57 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '_apple-mobdev._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] },
|
||||
{ name: '46c20544._sub._apple-mobdev2._tcp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] },
|
||||
{ name: '_sleep-proxy._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer: [],
|
||||
authority: [],
|
||||
additional:
|
||||
[ { name: '',
|
||||
type: 41,
|
||||
class: 1440,
|
||||
ttl: 4500,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
opt:
|
||||
{ code: 4,
|
||||
data: <Buffer 00 00 08 00 27 00 d4 b4>,
|
||||
rcode: 0,
|
||||
version: 0,
|
||||
do: 0,
|
||||
z: 4500 } } ],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '0.7.9.b.4.e.a.3.0.d.3.7.3.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa',
|
||||
type: 255,
|
||||
class: 32769 },
|
||||
{ name: '0.7.9.b.4.e.a.3.0.d.3.7.3.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa',
|
||||
type: 255,
|
||||
class: 32769 } ],
|
||||
answer: [],
|
||||
authority:
|
||||
[ { name: '0.7.9.b.4.e.a.3.0.d.3.7.3.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' },
|
||||
{ name: '0.7.9.b.4.e.a.3.0.d.3.7.3.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' } ],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '11.1.0.10.in-addr.arpa', type: 255, class: 32769 },
|
||||
{ name: '11.1.0.10.in-addr.arpa', type: 255, class: 32769 } ],
|
||||
answer: [],
|
||||
authority:
|
||||
[ { name: '11.1.0.10.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' },
|
||||
{ name: '11.1.0.10.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' } ],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 0,
|
||||
opcode: 0,
|
||||
aa: 0,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '11.1.0.10.in-addr.arpa', type: 255, class: 32769 },
|
||||
{ name: '11.1.0.10.in-addr.arpa', type: 255, class: 32769 } ],
|
||||
answer: [],
|
||||
authority:
|
||||
[ { name: '11.1.0.10.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' },
|
||||
{ name: '11.1.0.10.in-addr.arpa',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 120,
|
||||
data: 'Apple-TV-2.local' } ],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
BIN
node_modules/dns-js/test/fixtures/mdns-inbound-linux_workstation.bin
generated
vendored
Normal file
BIN
node_modules/dns-js/test/fixtures/mdns-inbound-linux_workstation.bin
generated
vendored
Normal file
Binary file not shown.
28
node_modules/dns-js/test/fixtures/mdns-inbound-linux_workstation.js
generated
vendored
Normal file
28
node_modules/dns-js/test/fixtures/mdns-inbound-linux_workstation.js
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 1,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question: [ { name: '_services._dns-sd._udp.local', type: 12, class: 1 } ],
|
||||
answer:
|
||||
[ { name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
data: '_workstation._tcp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
data: '_udisks-ssh._tcp.local' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Binary file not shown.
|
@ -0,0 +1,80 @@
|
|||
{ header:
|
||||
{ id: 0,
|
||||
qr: 1,
|
||||
opcode: 0,
|
||||
aa: 1,
|
||||
tc: 0,
|
||||
rd: 0,
|
||||
ra: 0,
|
||||
res1: 0,
|
||||
res2: 0,
|
||||
res3: 0,
|
||||
rcode: 0 },
|
||||
question:
|
||||
[ { name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 3600,
|
||||
isQD: true,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter] } ],
|
||||
answer:
|
||||
[ { name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_sleep-proxy._udp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_acp-sync._tcp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_airport._tcp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_raop._tcp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_airplay._tcp.local' },
|
||||
{ name: '_services._dns-sd._udp.local',
|
||||
type: 12,
|
||||
class: 1,
|
||||
ttl: 10,
|
||||
isQD: false,
|
||||
typeName: [Getter],
|
||||
className: [Getter],
|
||||
flag: [Getter],
|
||||
data: '_afpovertcp._tcp.local' } ],
|
||||
authority: [],
|
||||
additional: [],
|
||||
edns_options: [],
|
||||
payload: undefined }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue