feat(discover): add discover

This commit is contained in:
2023-07-12 16:59:59 +02:00
parent 329b222e67
commit dedce2a891
4 changed files with 101 additions and 40 deletions
+80 -8
View File
@@ -2,7 +2,12 @@ import {
Container,
AuthenticationRequest,
AuthenticationResponse,
Message
Message,
PublishRequest,
PublishResponse,
DiscoverRequest,
DiscoverResponse,
DiscoverPeer
} from './Protocol.js'
import { EventEmitter } from 'node:events'
@@ -21,8 +26,10 @@ export class Peer extends EventEmitter {
this.#salt = salt
this.#msgMap = new Map()
this.#msgMap.set('AuthenticationRequest', this.#onauth)
this.#msgMap.set('AuthenticationRequest', this.#onauthrequest)
this.#msgMap.set('Message', this.#onmessage)
this.#msgMap.set('PublishRequest', this.#onpublishrequest)
this.#msgMap.set('DiscoverRequest', this.#ondiscoverrequest)
this.#setupListeners()
}
@@ -51,7 +58,9 @@ export class Peer extends EventEmitter {
}
})
this.on('incoming', ({ source, message }) => {
}
onincoming(source, message) {
this.#send({
id: this.#id++,
message: Message.create({
@@ -60,7 +69,6 @@ export class Peer extends EventEmitter {
data: message.Message.data
})
})
})
}
#send({ id, message }) {
@@ -74,7 +82,7 @@ export class Peer extends EventEmitter {
this.#socket.send(buf)
}
#onauth(message) {
#onauthrequest(message) {
const { seed } = AuthenticationRequest.toObject(message.AuthenticationRequest, { longs: String })
if(this.#address !== null) {
this.#send({
@@ -105,9 +113,73 @@ export class Peer extends EventEmitter {
#onmessage(message) {
const { address } = Message.toObject(message.Message, { longs: String })
this.emit('outgoing', {
destination: BigInt(address),
message
const bigint = BigInt(address)
const destPeer = this.server.peers.find(p => p.address === bigint)
if(destPeer) {
destPeer.onincoming(this, message)
}
}
#publish(port, flags) {
const service = this.server.discover.find(sv => sv.peer === this && sv.port === port)
if(service) {
return false
}
this.server.discover.push({
peer: this,
port,
flags
})
return true
}
#unpublish(port) {
this.server.discover = this.server.discover.filter(sv => !(sv.peer === this && sv.port === port))
return true
}
#onpublishrequest(message) {
const { port, publish, flags } = PublishRequest.toObject(message.PublishRequest)
let ret
if(publish) {
ret = this.#publish(port, flags)
} else {
ret = this.#unpublish(port)
}
this.#send({
id: message.id,
message: PublishResponse.create({
status: ret ? 0: 1
})
})
}
#ondiscoverrequest(message) {
const { limit, flags } = DiscoverRequest.toObject(message.DiscoverRequest)
let services = this.server.discover.filter(sv => sv.flags.find(flag => flags.includes(flag)))
if(limit !== 0) {
services = services.slice(0, limit)
}
const discoverPeers = services.map(sv => {
return DiscoverPeer.create({
port: sv.port,
address: sv.peer.address.toString(10),
flags: sv.flags
})
})
this.#send({
id: message.id,
message: DiscoverResponse.create({
status: 0,
peers: discoverPeers
})
})
}
+3 -2
View File
@@ -23,8 +23,9 @@ export const [
PublishRequest,
PublishResponse,
DiscoverRequest,
DiscoverResponse
] = await import_proto('2.0/PublishDiscover.proto', ['PublishRequest', 'PublishResponse', 'DiscoverRequest', 'DiscoverResponse'])
DiscoverResponse,
DiscoverPeer
] = await import_proto('2.0/PublishDiscover.proto', ['PublishRequest', 'PublishResponse', 'DiscoverRequest', 'DiscoverResponse', 'DiscoverPeer'])
export const messages = [
Container,
+8 -20
View File
@@ -22,25 +22,18 @@ export class Server {
#salt = null
#wss = null
#options = Object.create(null)
#peers = []
constructor({ deflate = false, salt }) {
this.discover = []
this.peers = []
if(deflate) {
this.#options.perMessageDeflate = DEFAULT_OPTIONS
}
this.#salt = salt
}
#randomizeAddress() {
let address
while(!address || this.#peers.find(peer => peer.address.compare(address) === 0)) {
address = randomBytes(8)
}
return address
}
listen(port) {
const wss = new WebSocketServer({
...this.#options,
@@ -53,17 +46,12 @@ export class Server {
socket
})
peer.on('outgoing', ({ destination, message }) => {
const destPeer = this.#peers.find(p => p.address === destination)
if(destPeer) {
destPeer.emit('incoming', { source: peer, message })
}
})
this.#peers.push(peer)
peer.server = this
this.peers.push(peer)
socket.on('close', () => {
this.#peers = this.#peers.filter(p => p !== peer)
this.peers = this.peers.filter(p => p !== peer)
this.discover = this.discover.filter(sv => sv.peer !== peer)
})
})