Initial commit
This commit is contained in:
+105
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
Container,
|
||||
AuthenticationRequest,
|
||||
AuthenticationResponse,
|
||||
Message
|
||||
} from './Protocol.js'
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
const WebSocket = (typeof window === 'undefined' ? import('ws'): window.WebSocket)
|
||||
|
||||
export class Client extends EventEmitter {
|
||||
#gateway
|
||||
#ws
|
||||
#id
|
||||
#address
|
||||
|
||||
constructor(gateway) {
|
||||
super()
|
||||
this.#id = 0
|
||||
this.#gateway = gateway
|
||||
}
|
||||
|
||||
#protoSend({ id, message }) {
|
||||
const container = Container.create({
|
||||
id,
|
||||
[message.constructor.name]: message
|
||||
})
|
||||
|
||||
const buf = Container.encode(container).finish()
|
||||
console.log('sending:', buf)
|
||||
this.#ws.send(buf)
|
||||
}
|
||||
|
||||
#protoRequest(message) {
|
||||
const id = this.#id++
|
||||
|
||||
return new Promise(resolve => {
|
||||
const onReceive = container => {
|
||||
if(container.id === id) {
|
||||
resolve(container)
|
||||
this.removeListener('raw', onReceive)
|
||||
}
|
||||
}
|
||||
|
||||
this.on('raw', onReceive)
|
||||
this.#protoSend({
|
||||
id,
|
||||
message
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
login({ seed }) {
|
||||
const ws = new WebSocket(this.#gateway)
|
||||
this.#ws = ws
|
||||
|
||||
ws.onopen = async () => {
|
||||
const response = await this.#protoRequest(AuthenticationRequest.create({ seed }))
|
||||
const auth = AuthenticationResponse.toObject(response.AuthenticationResponse, { longs: String })
|
||||
this.#address = BigInt(auth.address)
|
||||
|
||||
this.emit('ready')
|
||||
}
|
||||
|
||||
ws.onmessage = async ({ data }) => {
|
||||
const message = Container.decode(new Uint8Array(await data.arrayBuffer()))
|
||||
const container = Container.toObject(message, {
|
||||
oneofs: true
|
||||
})
|
||||
|
||||
this.emit('raw', container)
|
||||
}
|
||||
|
||||
ws.onclose = () => {
|
||||
}
|
||||
}
|
||||
|
||||
send(destination, port, data) {
|
||||
if(typeof destination === 'bigint') {
|
||||
destination = destination.toString(10)
|
||||
}
|
||||
|
||||
this.#protoSend({
|
||||
id: this.#id++,
|
||||
message: Message.create({
|
||||
address: destination,
|
||||
port,
|
||||
data
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
get address() {
|
||||
return this.#address
|
||||
}
|
||||
|
||||
listen(port, callback) {
|
||||
this.on('raw', container => {
|
||||
if(container.message === 'Message') {
|
||||
const message = Message.toObject(container.Message, { longs: String })
|
||||
callback(BigInt(message.address), message.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import encoders from './protocol.json' assert { type: 'json' }
|
||||
import protobuf from 'protobufjs'
|
||||
import Long from 'long'
|
||||
|
||||
protobuf.util.Long = Long
|
||||
protobuf.configure()
|
||||
|
||||
const import_proto = (descriptor, types) => {
|
||||
const proto = protobuf.Root.fromJSON(descriptor)
|
||||
return types.map(type => proto.lookupType(type))
|
||||
}
|
||||
|
||||
export const [
|
||||
Container,
|
||||
AuthenticationRequest,
|
||||
AuthenticationResponse,
|
||||
Message,
|
||||
PublishRequest,
|
||||
PublishResponse,
|
||||
DiscoverRequest,
|
||||
DiscoverResponse
|
||||
] = import_proto(protocol20, [
|
||||
'Container',
|
||||
'AuthenticationRequest',
|
||||
'AuthenticationResponse',
|
||||
'Message',
|
||||
'PublishRequest',
|
||||
'PublishResponse',
|
||||
'DiscoverRequest',
|
||||
'DiscoverResponse'
|
||||
])
|
||||
|
||||
export const messages = [
|
||||
Container,
|
||||
AuthenticationRequest,
|
||||
AuthenticationResponse,
|
||||
Message,
|
||||
PublishRequest,
|
||||
PublishResponse,
|
||||
DiscoverRequest,
|
||||
DiscoverResponse
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
import Long from 'long'
|
||||
import { Client } from './Client.js'
|
||||
|
||||
export function formatAddress(address) {
|
||||
const int = BigInt(address)
|
||||
return int.toString(16).padStart(16, '0').match(/.{1,4}/g).join(':')
|
||||
}
|
||||
|
||||
export function decodeAddress(address) {
|
||||
return Long.fromString(BigInt('0x' + address.replace(/:/g, '')).toString(10))
|
||||
}
|
||||
|
||||
export { Client }
|
||||
Submodule
+1
Submodule src/protocol added at d0747faf68
Reference in New Issue
Block a user