source: trip-planner-front/node_modules/multicast-dns/index.js@ ceaed42

Last change on this file since ceaed42 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.7 KB
Line 
1var packet = require('dns-packet')
2var dgram = require('dgram')
3var thunky = require('thunky')
4var events = require('events')
5var os = require('os')
6
7var noop = function () {}
8
9module.exports = function (opts) {
10 if (!opts) opts = {}
11
12 var that = new events.EventEmitter()
13 var port = typeof opts.port === 'number' ? opts.port : 5353
14 var type = opts.type || 'udp4'
15 var ip = opts.ip || opts.host || (type === 'udp4' ? '224.0.0.251' : null)
16 var me = {address: ip, port: port}
17 var memberships = {}
18 var destroyed = false
19 var interval = null
20
21 if (type === 'udp6' && (!ip || !opts.interface)) {
22 throw new Error('For IPv6 multicast you must specify `ip` and `interface`')
23 }
24
25 var socket = opts.socket || dgram.createSocket({
26 type: type,
27 reuseAddr: opts.reuseAddr !== false,
28 toString: function () {
29 return type
30 }
31 })
32
33 socket.on('error', function (err) {
34 if (err.code === 'EACCES' || err.code === 'EADDRINUSE') that.emit('error', err)
35 else that.emit('warning', err)
36 })
37
38 socket.on('message', function (message, rinfo) {
39 try {
40 message = packet.decode(message)
41 } catch (err) {
42 that.emit('warning', err)
43 return
44 }
45
46 that.emit('packet', message, rinfo)
47
48 if (message.type === 'query') that.emit('query', message, rinfo)
49 if (message.type === 'response') that.emit('response', message, rinfo)
50 })
51
52 socket.on('listening', function () {
53 if (!port) port = me.port = socket.address().port
54 if (opts.multicast !== false) {
55 that.update()
56 interval = setInterval(that.update, 5000)
57 socket.setMulticastTTL(opts.ttl || 255)
58 socket.setMulticastLoopback(opts.loopback !== false)
59 }
60 })
61
62 var bind = thunky(function (cb) {
63 if (!port) return cb(null)
64 socket.once('error', cb)
65 socket.bind(port, opts.interface, function () {
66 socket.removeListener('error', cb)
67 cb(null)
68 })
69 })
70
71 bind(function (err) {
72 if (err) return that.emit('error', err)
73 that.emit('ready')
74 })
75
76 that.send = function (value, rinfo, cb) {
77 if (typeof rinfo === 'function') return that.send(value, null, rinfo)
78 if (!cb) cb = noop
79 if (!rinfo) rinfo = me
80
81 bind(onbind)
82
83 function onbind (err) {
84 if (destroyed) return cb()
85 if (err) return cb(err)
86 var message = packet.encode(value)
87 socket.send(message, 0, message.length, rinfo.port, rinfo.address || rinfo.host, cb)
88 }
89 }
90
91 that.response =
92 that.respond = function (res, rinfo, cb) {
93 if (Array.isArray(res)) res = {answers: res}
94
95 res.type = 'response'
96 res.flags = (res.flags || 0) | packet.AUTHORITATIVE_ANSWER
97 that.send(res, rinfo, cb)
98 }
99
100 that.query = function (q, type, rinfo, cb) {
101 if (typeof type === 'function') return that.query(q, null, null, type)
102 if (typeof type === 'object' && type && type.port) return that.query(q, null, type, rinfo)
103 if (typeof rinfo === 'function') return that.query(q, type, null, rinfo)
104 if (!cb) cb = noop
105
106 if (typeof q === 'string') q = [{name: q, type: type || 'ANY'}]
107 if (Array.isArray(q)) q = {type: 'query', questions: q}
108
109 q.type = 'query'
110 that.send(q, rinfo, cb)
111 }
112
113 that.destroy = function (cb) {
114 if (!cb) cb = noop
115 if (destroyed) return process.nextTick(cb)
116 destroyed = true
117 clearInterval(interval)
118 socket.once('close', cb)
119 socket.close()
120 }
121
122 that.update = function () {
123 var ifaces = opts.interface ? [].concat(opts.interface) : allInterfaces()
124 var updated = false
125
126 for (var i = 0; i < ifaces.length; i++) {
127 var addr = ifaces[i]
128
129 if (memberships[addr]) continue
130 memberships[addr] = true
131 updated = true
132
133 try {
134 socket.addMembership(ip, addr)
135 } catch (err) {
136 that.emit('warning', err)
137 }
138 }
139
140 if (!updated || !socket.setMulticastInterface) return
141 socket.setMulticastInterface(opts.interface || defaultInterface())
142 }
143
144 return that
145}
146
147function defaultInterface () {
148 var networks = os.networkInterfaces()
149 var names = Object.keys(networks)
150
151 for (var i = 0; i < names.length; i++) {
152 var net = networks[names[i]]
153 for (var j = 0; j < net.length; j++) {
154 var iface = net[j]
155 if (iface.family === 'IPv4' && !iface.internal) return iface.address
156 }
157 }
158
159 return '127.0.0.1'
160}
161
162function allInterfaces () {
163 var networks = os.networkInterfaces()
164 var names = Object.keys(networks)
165 var res = []
166
167 for (var i = 0; i < names.length; i++) {
168 var net = networks[names[i]]
169 for (var j = 0; j < net.length; j++) {
170 var iface = net[j]
171 if (iface.family === 'IPv4') {
172 res.push(iface.address)
173 // could only addMembership once per interface (https://nodejs.org/api/dgram.html#dgram_socket_addmembership_multicastaddress_multicastinterface)
174 break
175 }
176 }
177 }
178
179 return res
180}
Note: See TracBrowser for help on using the repository browser.