72 lines
1.4 KiB
JavaScript
72 lines
1.4 KiB
JavaScript
'use strict'
|
|
|
|
const crypto = require('crypto')
|
|
|
|
class Node {
|
|
static generateID() {
|
|
return crypto.createHash('sha1').update(crypto.randomBytes(20)).digest()
|
|
}
|
|
|
|
constructor(id) {
|
|
this.id = id || Node.generateNodeID()
|
|
}
|
|
|
|
static neighbor(target, id) {
|
|
return Buffer.concat([target.slice(0, 10), id.slice(10)])
|
|
}
|
|
|
|
static encodeNodes(nodes) {
|
|
return Buffer.concat(nodes.map((node)=> Buffer.concat([node.id, Node.encodeIP(node.address), Node.encodePort(node.port)])))
|
|
}
|
|
|
|
static decodeNodes(data) {
|
|
const nodes = []
|
|
for (let i = 0; i + 26 <= data.length; i += 26) {
|
|
nodes.push({
|
|
id: data.slice(i, i + 20),
|
|
address: `${data[i + 20]}.${data[i + 21]}.${data[i + 22]}.${data[i + 23]}`,
|
|
port: data.readUInt16BE(i + 24)
|
|
})
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
static encodeIP(ip) {
|
|
return Buffer.from(ip.split('.').map((i)=>parseInt(i)))
|
|
}
|
|
|
|
static encodePort(port) {
|
|
const data = Buffer.alloc(2)
|
|
data.writeUInt16BE(port, 0)
|
|
return data
|
|
}
|
|
}
|
|
|
|
class Table{
|
|
constructor(cap) {
|
|
this.id = Node.generateID()
|
|
this.nodes = []
|
|
this.caption = cap
|
|
}
|
|
add(node) {
|
|
if (this.nodes.length < this.caption) {
|
|
this.nodes.push(node)
|
|
}
|
|
}
|
|
shift() {
|
|
return this.nodes.shift()
|
|
}
|
|
size() {
|
|
return this.nodes.length;
|
|
}
|
|
first() {
|
|
if(this.nodes.length >= 8) {
|
|
return this.nodes.slice(0, 8)
|
|
}else if(this.nodes.length > 0) {
|
|
return new Array(8).join().split(',').map(()=> this.nodes[0])
|
|
}
|
|
return []
|
|
}
|
|
}
|
|
|
|
module.exports = {Table, Node} |