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