VimUnDo{UPjł(Ne'B!????>S_vS// TODO: ipv6 support5// TODO: parse and send peer flags (currently unused)B// NOTE: addPeer should take in an optional second argument, flags?// TODO: destroy wire if peer sends PEX messages too frequently1var EventEmitter = require('events').EventEmitter.var compact2string = require('compact2string').var string2compact = require('string2compact') var bencode = require('bencode')"var inherits = require('inherits')1var PEX_INTERVAL = 65000 // just over one minuteMvar PEX_MAX_PEERS = 50 // max number of peers to advertise per PEX messagemodule.exports = function () { inherits(ut_pex, EventEmitter) function ut_pex (wire) { var self = this EventEmitter.call(self) self._wire = wire self._intervalId = null self.reset() } /**6 * Start sending regular PEX updates to remote peer. */( ut_pex.prototype.start = function () { var self = this# clearInterval(self._intervalId)N self._intervalId = setInterval(self._sendMessage.bind(self), PEX_INTERVAL) } /**1 * Stop sending PEX updates to the remote peer. */' ut_pex.prototype.stop = function () { var self = this# clearInterval(self._intervalId) self._intervalId = null } /**V * Stops sending updates to the remote peer and resets internal state of peers seen. */( ut_pex.prototype.reset = function () { var self = this self._remoteAddedPeers = {}! self._remoteDroppedPeers = {} self._localAddedPeers = {} self._localDroppedPeers = {} self.stop() } /**N * Adds a peer to the locally discovered peer list for the next PEX message. */. ut_pex.prototype.addPeer = function (peer) { var self = this@ if (peer.indexOf(':') < 0) return // disregard invalid peersf if (peer in self._remoteAddedPeers) return // never advertise peer the remote wire already sent usM if (peer in self._localDroppedPeers) delete self._localDroppedPeers[peer]& self._localAddedPeers[peer] = true } /**K * Adds a peer to the locally dropped peer list for the next PEX message. *// ut_pex.prototype.dropPeer = function (peer) { var self = this@ if (peer.indexOf(':') < 0) return // disregard invalid peersh if (peer in self._remoteDroppedPeers) return // never advertise peer the remote wire already sent usI if (peer in self._localAddedPeers) delete self._localAddedPeers[peer]( self._localDroppedPeers[peer] = true }? ut_pex.prototype.onExtendedHandshake = function (handshake) { var self = this. if (!handshake.m || !handshake.m.ut_pex) {L return self.emit('warning', new Error('Peer does not support ut_pex')) } } /**D * PEX messages are bencoded dictionaries with the following keys:< * 'added' : array of peers met since last PEX message* * 'added.f' : array of flags per peer* * '0x01' : peer prefers encryption! * '0x02' : peer is seederS * 'dropped' : array of peers locally dropped from swarm since last PEX message* * 'added6' : ipv6 version of 'added', * 'added6.f' : ipv6 version of 'added.f', * 'dropped.f' : ipv6 version of 'dropped' *0 * @param {Buffer} buf bencoded PEX dictionary *// ut_pex.prototype.onMessage = function (buf) { var self = this var message try {# message = bencode.decode(buf) } catch (err) { // drop invalid messages return } if (message.added) {C compact2string.multi(message.added).forEach(function (peer) {0 if (!(peer in self._remoteAddedPeers)) {- self._remoteAddedPeers[peer] = true! self.emit('peer', peer) } }) } if (message.dropped) {E compact2string.multi(message.dropped).forEach(function (peer) {+ delete self._remoteAddedPeers[peer]- self._remoteDroppedPeers[peer] = true" self.emit('dropped', peer) }) } } /**S * Sends a PEX message to the remote peer including information about any locally * added / dropped peers. *// ut_pex.prototype._sendMessage = function () { var self = thisQ var localAdded = Object.keys(self._localAddedPeers).slice(0, PEX_MAX_PEERS)Q var localDropped = Object.keys(self._localAddedPeers).slice(0, PEX_MAX_PEERS)? var added = Buffer.concat(localAdded.map(string2compact))A var dropped = Buffer.concat(localDropped.map(string2compact))? var addedFlags = Buffer.concat(localAdded.map(function () { // TODO: support flags return new Buffer([0]) })) // update local deltasN localAdded.forEach(function (peer) { delete self._localAddedPeers[peer] })R localDropped.forEach(function (peer) { delete self._localDroppedPeers[peer] }) // send PEX message# self._wire.extended('ut_pex', { 'added': added, 'added.f': addedFlags, 'dropped': dropped, 'added6': new Buffer(0), 'added6.f': new Buffer(0), 'dropped6': new Buffer(0) }) } return ut_pex}5_vS5_vS};5_vS5_vS return that; }); that.add(block); }; return tree.contains(addr);7 if (typeof addr !== 'number') addr = ip.toLong(addr); if (!tree) return false; };( else tree = new BlockTree(start, end);! if (tree) tree.add(start, end);[ if (start < 0 || end > 4294967295 || end < start) throw new Error('Invalid block range');4 if (typeof end !== 'number') end = ip.toLong(end); if (!end) end = start;}: if (typeof start !== 'number') start = ip.toLong(start);z| start = start.start;y{ end = start.end;wy if (!start) return;tv var that = {};su var tree = null;pr};oq return node ? true : false;mo else node = node.right;ln; if (node.left && node.left.max >= addr) node = node.left;jl var node = this;gi};fh return update;eg if (update) this.update();ac update = true;`b* this.right = new BlockTree(start, end);^` if (update) this.balance();]_' update = this.right.add(start, end);Y[ update = true;XZ) this.left = new BlockTree(start, end);VX if (update) this.balance();UW& update = this.left.add(start, end);RT update = true;QS this.end = end;NP var update = false;MO var d = start - this.start;JL};IK_ this.max = Math.max(this.end, this.left ? this.left.max : 0, this.right ? this.right.max : 0);HJU if (this.right && this.depth <= this.right.depth) this.depth = this.right.depth + 1;GI1 if (this.left) this.depth = this.left.depth + 1;FH this.depth = 1;CE};BD this.update();AC this.left.update();?A this.left.end = _end;>@ this.left.start = _start;=? this.left.left = _left;<>" this.left.right = this.left.left;:< this.right = this.right.right;9; this.left = this.right;8: this.end = this.right.end;79 this.end = this.right.end;68 this.start = this.right.start;46 var _left = this.left;35 var _end = this.end;24 var _start = this.start;/1};.0 this.update();-/ this.right.update();+- this.right.end = _end;*, this.right.start = _start;)+ this.right.right = _right;(*$ this.right.left = this.right.right;&( this.left = this.left.left;%' this.right = this.left;$& this.end = this.left.end;#% this.start = this.left.start;!# var _right = this.right; " var _end = this.end;! var _start = this.start;}; this.rotateRR();/ if (rldepth > rrdepth) this.right.rotateLL();< var rldepth = this.right.left ? this.right.left.depth : 0;> var rrdepth = this.right.right ? this.right.right.depth : 0; this.rotateLL();. if (lldepth < lrdepth) this.left.rotateRR();< var lrdepth = this.left.right ? this.left.right.depth : 0;: var lldepth = this.left.left ? this.left.left.depth : 0;0 var rdepth = this.right ? this.right.depth : 0;. var ldepth = this.left ? this.left.depth : 0;  this.right = null;  this.left = null;  this.depth = 1;  this.max = end; this.end = end; this.start = start;var ip = require('ip');5_uvStv var that = {}5_wvSvx" that.add = function(start, end) {5_ vS! that.contains = function(addr) {5_ vS that.add(block)5_ vS return that5_ vS function BlockTree(start, end) {5_ vS  this.left = null5_    v S  this.right = null  this.left = null  this.depth = 1  this.max = end this.end = end this.start = start5_   v S this.rotateLL()5_$  v S. if (rldepth > rrdepth) this.right.rotateLL()5_  v S +BlockTree.prototype.rotateLL = function() {5_#  v S- if (lldepth < lrdepth) this.left.rotateRR()5_  v S  this.rotateRR()5_2  v S 13+BlockTree.prototype.rotateRR = function() {5_. 3 Av S-/ this.right.update()5_/3 Av S.0 this.update()5_B 3 Av S AC this.left.update()5_C3 Av S BD this.update()5_F3 Av S!EG)BlockTree.prototype.update = function() {5_ f3 Av S.eg if (update) this.update()5_! 3 Av S6% blocklist.forEach(function(block) {! self.contains = function(addr) {vx" self.add = function(start, end) {rt&module.exports = function(blocklist) {ik/BlockTree.prototype.contains = function(addr) {LN0BlockTree.prototype.add = function(start, end) {EG*BlockTree.prototype._update = function() {13,BlockTree.prototype._rotateRR = function() { ,BlockTree.prototype._rotateLL = function() { *BlockTree.prototype.balance = function() {5_ "!3 Av S[/* jshint camelcase: false */5_!#" 2 @v S!function BlockTree (start, end) {5_"$# 2 @v S +BlockTree.prototype.balance = function () {5_#%$2 @v S-BlockTree.prototype._rotateLL = function () {5_$&%12 @v S02-BlockTree.prototype._rotateRR = function () {5_%'&E2 @v SDF+BlockTree.prototype._update = function () {5_&('L2 @v SKM1BlockTree.prototype.add = function (start, end) {5_')(X2 @v SWY( this.left = new BlockTree(start, end)5_(*)`2 @v S_a) this.right = new BlockTree(start, end)5_)+*i2 @v Shj0BlockTree.prototype.contains = function (addr) {5_*,+2 @v S ' else tree = new BlockTree(start, end)5_+-,o2 @v S np return node ? true : false5_,.- 2 @v S ! var _end = this.end5_-/.$ $ $ v S#% this.end = this.left.end5_.0/& $ $ v S%' this.left = this.left.left5_/10($ $ v S')# this.right.left = this.right.right5_021+$ $ v S*, this.right.end = _end5_1323 $ $ v S24 var _end = this.end5_2434 $ $ v S35 var _left = this.left5_3547 $ $ v S68 this.end = this.right.end5_4657 $ $ v S68 this.end = this.right.end5_5768 $ $ v S79 this.end = this.right.end5_6879 $ $ v S 8: this.left = this.right5_798=$ $ v S,<> this.left.left = _left5_8:9???vS1 >@ this.left.end = _end5_9;:KKpvSJL'-IPSet.prototype.add = function (start, end) { var d = start - this.start var update = false! if (d === 0 && this.end < end) { this.end = end update = true } else if (d < 0) { if (this.left) {% update = this.left.add(start, end) if (update) this.balance() } else {$ this.left = new IPSet(start, end) update = true } } else if (d > 0) { if (this.right) {& update = this.right.add(start, end) if (update) this.balance() } else {% this.right = new IPSet(start, end) update = true } } if (update) this._update() return update},IPSet.prototype.contains = function (addr) { var node = this< while (node && !(addr >= node.start && addr <= node.end)) {: if (node.left && node.left.max >= addr) node = node.left else node = node.right } return !!node}5_:<; KKvS 3p p5_;=<qqvS if (update) this.balance()5_<>=qqvS  if (update) this.balance()5_=?>3qqvS24'IPSet.prototype.balance = function () {5_>?ppvS5_O3 Av S"NP var _update = false5_33 Av S24 var _start = this.start35 var _end = this.end46 var _left = this.left5768# this.start = this.right.start79! this.end = this.right.end8:! this.end = this.right.end9; this.left = this.right:<# this.right = this.right.right;=<>! this.left.right = this.left.left=? this.left.left = _left>@ this.left.start = _start?A this.left.end = _end@B5_   v S. var ldepth = this.left ? this.left.depth : 05_+  v S/ var ldepth = this.left ? this.left.depth : 05_  v S: var lldepth = this.left.left ? this.left.left.depth : 05_7  v S; var lldepth = this.left.left ? this.left.left.depth : 05