Initial commit
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*.{js,json}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
@@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/**
|
||||
src/protocol.json
|
||||
!.gitkeep
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "src/protocol"]
|
||||
path = src/protocol
|
||||
url = https://git.sys36.net/windows-96/ppp2/protocol
|
||||
@@ -0,0 +1,8 @@
|
||||
# ppp2 client
|
||||
|
||||
## building
|
||||
```
|
||||
$ npm i
|
||||
$ npm run build-proto
|
||||
$ npm run build
|
||||
```
|
||||
Vendored
Generated
+3793
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "ppp2-client",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build-proto": "NODE_VERSION=19 npm_config_prefix= $HOME/.nvm/nvm-exec ./node_modules/protobufjs-cli/bin/pbjs -t=json src/protocol/protobuf/2.0/*.proto > src/protocol.json",
|
||||
"dev": "NODE_ENV=development webpack watch",
|
||||
"build": "NODE_ENV=production webpack",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@git.sys36.net:windows-96/ppp2/client.git"
|
||||
},
|
||||
"author": "",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"long": "^5.2.1",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"protobufjs-cli": "^1.1.1",
|
||||
"webpack": "^5.76.3",
|
||||
"webpack-cli": "^5.0.1"
|
||||
}
|
||||
}
|
||||
+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
@@ -0,0 +1,21 @@
|
||||
import { resolve, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import webpack from 'webpack'
|
||||
|
||||
export default {
|
||||
mode: process.env.NODE_ENV || 'production',
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
library: {type:'module'},
|
||||
filename: 'ppp2.js',
|
||||
path: resolve(fileURLToPath(join(import.meta.url, '..')), 'dist')
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1
|
||||
})
|
||||
],
|
||||
experiments: {
|
||||
outputModule: true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user