relay: Add multi-user login support (#258)
* relay: add multi-user login support * relay: Fix close handling, connect username
This commit is contained in:
parent
ce06762dce
commit
c395f0b05b
3 changed files with 38 additions and 5 deletions
|
|
@ -170,7 +170,7 @@ For documentation on the protocol, and packets/fields see the [the protocol doc]
|
|||
|
||||
### Proxy docs
|
||||
|
||||
You can create a proxy ("Relay") to create a machine-in-the-middle (MITM) connection to a server. You can observe and intercept packets as they go through. The Relay is a server+client combo with some special packet handling and forwarding that takes care of the authentication and encryption on the server side. You'll be asked to login if `offline` is not specified once you connect.
|
||||
You can create a proxy ("Relay") to create a machine-in-the-middle (MITM) connection to a server. You can observe and intercept packets as they go through. The Relay is a server+client combo with some special packet handling and forwarding that takes care of the authentication and encryption on the server side. Clients will be asked to login if `offline` is not specified on connection.
|
||||
|
||||
```js
|
||||
const { Relay } = require('bedrock-protocol')
|
||||
|
|
|
|||
12
index.d.ts
vendored
12
index.d.ts
vendored
|
|
@ -131,6 +131,10 @@ declare module "bedrock-protocol" {
|
|||
* Close the connection. Already called by disconnect. Call this to manually close RakNet connection.
|
||||
*/
|
||||
close()
|
||||
|
||||
on(event: 'login', cb: () => void)
|
||||
on(event: 'join', cb: () => void)
|
||||
on(event: 'close', cb: (reason: string) => void)
|
||||
}
|
||||
|
||||
export class Server extends EventEmitter {
|
||||
|
|
@ -161,6 +165,14 @@ declare module "bedrock-protocol" {
|
|||
}
|
||||
// Whether to enable chunk caching (default: false)
|
||||
enableChunkCaching?: boolean
|
||||
|
||||
// Only allow one client to connect at a time (default: false)
|
||||
forceSinge: boolean
|
||||
|
||||
// Dispatched when a new client has logged in, and we need authentication
|
||||
// tokens to join the backend server. Cached after the first login.
|
||||
// If this is not specified, the client will be disconnected with a login prompt.
|
||||
onMsaCode(data, client)
|
||||
}
|
||||
|
||||
export class Relay extends Server {
|
||||
|
|
|
|||
29
src/relay.js
29
src/relay.js
|
|
@ -159,7 +159,7 @@ class Relay extends Server {
|
|||
constructor (options) {
|
||||
super(options)
|
||||
this.RelayPlayer = options.relayPlayer || RelayPlayer
|
||||
this.forceSingle = true
|
||||
this.forceSingle = options.forceSingle
|
||||
this.upstreams = new Map()
|
||||
this.conLog = debug
|
||||
this.enableChunkCaching = options.enableChunkCaching
|
||||
|
|
@ -175,12 +175,18 @@ class Relay extends Server {
|
|||
const options = {
|
||||
authTitle: this.options.authTitle,
|
||||
offline: this.options.destination.offline ?? this.options.offline,
|
||||
username: this.options.offline ? ds.profile.name : null,
|
||||
username: this.options.offline ? ds.profile.name : ds.profile.xuid,
|
||||
version: this.options.version,
|
||||
realms: this.options.destination.realms,
|
||||
host: this.options.destination.host,
|
||||
port: this.options.destination.port,
|
||||
onMsaCode: this.options.onMsaCode,
|
||||
onMsaCode: (code) => {
|
||||
if (this.options.onMsaCode) {
|
||||
this.options.onMsaCode(code, ds)
|
||||
} else {
|
||||
ds.disconnect("It's your first time joining. Please sign in and reconnect to join this server:\n\n" + code.message)
|
||||
}
|
||||
},
|
||||
profilesFolder: this.options.profilesFolder,
|
||||
backend: this.options.backend,
|
||||
autoInitPlayer: false
|
||||
|
|
@ -213,6 +219,16 @@ class Relay extends Server {
|
|||
|
||||
this.emit('join', /* client connected to proxy */ ds, /* backend server */ client)
|
||||
})
|
||||
client.on('error', (err) => {
|
||||
ds.disconnect('Server error: ' + err.message)
|
||||
debug(clientAddr, 'was disconnected because of error', err)
|
||||
this.upstreams.delete(clientAddr.hash)
|
||||
})
|
||||
client.on('close', (reason) => {
|
||||
ds.disconnect('Backend server closed connection')
|
||||
this.upstreams.delete(clientAddr.hash)
|
||||
})
|
||||
|
||||
this.upstreams.set(clientAddr.hash, client)
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +241,7 @@ class Relay extends Server {
|
|||
this.conLog('closed upstream connection', clientAddr)
|
||||
}
|
||||
|
||||
// Called when a new player connects to our proxy server. Once the player has authenticted,
|
||||
// Called when a new player connects to our proxy server. Once the player has authenticated,
|
||||
// we can open an upstream connection to the backend server.
|
||||
onOpenConnection = (conn) => {
|
||||
if (this.forceSingle && this.clientCount > 0) {
|
||||
|
|
@ -240,6 +256,11 @@ class Relay extends Server {
|
|||
player.on('login', () => {
|
||||
this.openUpstreamConnection(player, conn.address)
|
||||
})
|
||||
player.on('close', (reason) => {
|
||||
this.conLog('player disconnected', conn.address, reason)
|
||||
this.clientCount--
|
||||
delete this.clients[conn.address]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue