cli: add proxy server

This commit is contained in:
pengfei.zhou 2023-08-11 16:24:10 +08:00 committed by jingpeng
parent 00cc673583
commit b61699a450
4 changed files with 143 additions and 7 deletions

View File

@ -5,6 +5,8 @@ import { build, clean, ssr } from "./actions";
import { create, createLib } from "./create" import { create, createLib } from "./create"
import dev from "./dev" import dev from "./dev"
import { run } from "./run"; import { run } from "./run";
import { linkProxyServer } from "./proxy";
import { createControlServer, startProxyServer } from "./proxyServer";
(process.env.FORCE_COLOR as any) = true (process.env.FORCE_COLOR as any) = true
@ -26,14 +28,21 @@ commander
commander commander
.command('dev') .command('dev')
.option('--proxy', 'Link proxy') .option('--proxy', 'Link proxy')
.action(async function (cmd, args) { .action(async function (_, args) {
const [proxy] = args const serverPort = 7777, resourcePort = 7778
await dev(serverPort, resourcePort)
const [proxy] = args ?? []
if (proxy) { if (proxy) {
console.log("Running in proxy mode", proxy) await linkProxyServer(`localhost:${serverPort}`, proxy)
} else {
await dev()
} }
}) })
commander
.command('proxy')
.option('--port', 'Link port')
.action(async function (_, args) {
const [proxy] = args ?? ["7780"]
await startProxyServer(parseInt(proxy))
})
commander commander
.command('build') .command('build')
.action(async function () { .action(async function () {

51
doric-cli/src/proxy.ts Normal file
View File

@ -0,0 +1,51 @@
import WebSocket from "ws"
import { MSG } from "./server"
export async function linkProxyServer(server: string, proxy: string) {
console.log("Running in proxy mode", proxy)
return new Promise<void>((resolve, reject) => {
const serverListener = new WebSocket(`ws://${server}`, {
headers: {
"role": "PROXY"
}
})
let proxyUserId: string | undefined = undefined
const controlConnector = new WebSocket(`ws://${proxy}`)
let transferConnector: WebSocket | undefined = undefined;
serverListener.on('open', () => {
console.log('Proxy attached to server', server)
resolve()
})
serverListener.on('message', (data) => {
transferConnector?.send(data)
})
serverListener.on('error', (error) => {
console.log(error)
transferConnector?.close()
controlConnector?.close()
reject(error)
})
controlConnector.on('open', () => {
console.log('Connected to proxy', proxy)
})
controlConnector.on('message', (data) => {
const msg = JSON.parse(data as string) as MSG
const payload = msg.payload
if (msg.cmd === "SetUserId") {
proxyUserId = payload.userId
const nextPort = payload.port
const transferAddr = proxy.replace(/:[0-9]*/, "") + ":" + nextPort
console.log("Get proxy UserId", proxyUserId, "addr", transferAddr)
transferConnector = new WebSocket("ws://" + transferAddr)
}
})
controlConnector.on('error', (error) => {
console.log(error)
transferConnector?.close()
controlConnector?.close()
reject(error)
})
})
}

View File

@ -0,0 +1,74 @@
import WebSocket from "ws"
import { MSG } from "./server";
import net from "net";
function findAvailablePort(startPort: number, callback: (port: number) => void) {
const port = startPort || 3000;
const server = net.createServer();
server.listen(port, () => {
server.once('close', () => {
callback(port);
});
server.close();
});
server.on('error', () => {
findAvailablePort(port + 1, callback);
});
}
export async function findAvailablePortAsync(startPort: number) {
return new Promise<number>((resolve) => {
findAvailablePort(startPort, (v) => {
resolve(v)
})
})
}
export async function createControlServer(port: number) {
let userId = 0
const wss = new WebSocket.Server({ port })
wss.on("connection", async (ws, request) => {
let thisUserId = `User#${userId++}`
const avaliablePort = await findAvailablePortAsync(3000)
console.log('Connected', request.headers.host)
console.log(`${thisUserId} attached to proxy server, port is ${avaliablePort}`.green)
ws.send(JSON.stringify({
type: "P2U",
cmd: "SetUserId",
payload: {
"userId": thisUserId,
"port": avaliablePort
}
}))
const transferServer = await createTransferServer(avaliablePort)
transferServer.on("connection", async function (ws) {
console.log(`${thisUserId} transferServer connection`)
ws.on("message", async function (result: string) {
console.log(`${thisUserId} received message`)
transferServer.clients.forEach(e => e.send(result))
})
})
ws.on('close', function (code: number) {
console.log('close: code = ' + code, thisUserId);
transferServer.close()
});
ws.on('error', function (code: number) {
console.log('error', code)
transferServer.close()
});
});
return wss;
}
export async function createTransferServer(port: number) {
const wss = new WebSocket.Server({ port })
return wss
}
export async function startProxyServer(port: number) {
const controlServer = await createControlServer(port)
console.log("Open Control Server on " + port)
}

View File

@ -20,8 +20,10 @@ export async function createServer(port: number) {
const wss = new WebSocket.Server({ port }) const wss = new WebSocket.Server({ port })
.on("connection", (ws, request) => { .on("connection", (ws, request) => {
let thisDeviceId: string let thisDeviceId: string
console.log('Connected', request.headers.host) if (request.headers["role"] === "PROXY") {
if (request.headers.host?.startsWith("localhost")) { thisDeviceId = `Client#${deviceId++}`
console.log(`PROXY ${thisDeviceId} attached to dev kit`.green)
} else if (request.headers["role"] === "DEBUGGER" || request.headers.host?.startsWith("localhost")) {
thisDeviceId = `Debugger#${deviceId++}` thisDeviceId = `Debugger#${deviceId++}`
console.log(`${thisDeviceId} attached to dev kit`.green) console.log(`${thisDeviceId} attached to dev kit`.green)
debug = ws; debug = ws;