Skip to content

Commit

Permalink
KCP byte check mode
Browse files Browse the repository at this point in the history
  • Loading branch information
NotArandomGUY committed Nov 26, 2023
1 parent b43f7af commit f01b58a
Show file tree
Hide file tree
Showing 8 changed files with 642 additions and 115 deletions.
2 changes: 1 addition & 1 deletion src/cli/commands/serverCommands/gsCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function suggestValue(): (string | number)[] {
const input = tty.getCurPrompt()?.buffer?.join('') || ''

const key = input.split(' ')[2]
if (input.indexOf('gs set') !== 0 || DEFAULT_GSTATE[key] == null) return
if (!input.startsWith('gs set') || DEFAULT_GSTATE[key] == null) return

const targetType = typeof DEFAULT_GSTATE[key]
switch (targetType) {
Expand Down
46 changes: 25 additions & 21 deletions src/globalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface GlobalStateData {
UseProtoMatch: boolean
WorldSpawn: boolean
GenerateSeed: boolean
ByteCheckMode: number
}

export const DEFAULT_GSTATE: GlobalStateData = {
Expand All @@ -34,16 +35,17 @@ export const DEFAULT_GSTATE: GlobalStateData = {
ShowPacketId: false,
UseProtoMatch: false,
WorldSpawn: true,
GenerateSeed: true
GenerateSeed: true,
ByteCheckMode: -1
}

export default class GlobalState {
static instance: GlobalState
private static instance: GlobalState

state: GlobalStateData
modified: boolean
private state: GlobalStateData
private modified: boolean

constructor() {
public constructor() {
this.state = { ...DEFAULT_GSTATE }
this.modified = false
}
Expand Down Expand Up @@ -76,20 +78,21 @@ export default class GlobalState {
}
}

static toggle(key: string) {
public static toggle(key: keyof GlobalStateData) {
GlobalState.getInstance().toggle(key)
}

toggle(key: string) {
public toggle(key: keyof GlobalStateData) {
const { state } = this

this.set(key, !state[key])
}

static set(key: string, val: GStateValue) {
public static set(key: keyof GlobalStateData, val: GStateValue) {
GlobalState.getInstance().set(key, val)
}

set(key: string, val: GStateValue) {
public set<K extends keyof GlobalStateData>(key: K, val: GStateValue) {
const { state } = this

if (state[key] == null) return logger.warn('Unknown global state:', key)
Expand All @@ -98,26 +101,26 @@ export default class GlobalState {
if (val == null) return logger.warn('Invalid type, value must be a ', typeof state[key])

if (state[key] !== val) {
state[key] = val
state[key] = <GlobalStateData[K]>val
this.modified = true
}

this.print(key)
}

static get(key: string): GStateValue {
public static get<K extends keyof GlobalStateData>(key: K): GlobalStateData[K] {
return GlobalState.getInstance().get(key)
}

get(key: string): GStateValue {
public get<K extends keyof GlobalStateData>(key: K): GlobalStateData[K] {
return this.state[key]
}

static print(key: string) {
public static print(key: keyof GlobalStateData) {
GlobalState.getInstance().print(key)
}

print(key: string) {
public print(key: keyof GlobalStateData) {
const val = this.get(key)
if (val == null) return

Expand All @@ -129,20 +132,21 @@ export default class GlobalState {
logger.info(msg)
}

static printAll() {
public static printAll() {
GlobalState.getInstance().printAll()
}

printAll() {
public printAll() {
const { state } = this
for (const key in state) this.print(key)

for (const key in state) this.print(<keyof GlobalStateData>key)
}

static load() {
public static load() {
GlobalState.getInstance().load()
}

load() {
public load() {
const { state } = this

try {
Expand All @@ -161,11 +165,11 @@ export default class GlobalState {
}
}

static save() {
public static save() {
GlobalState.getInstance().save()
}

save() {
public save() {
try {
if (!this.modified) {
logger.info('No changes detected.')
Expand Down
6 changes: 6 additions & 0 deletions src/kcpServer/socket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ export default class Socket extends BaseClass {

private async createKcpWorker(recvWorkerId: number, iPort: number, conv: number, connInfo: ConnectionInfo): Promise<KcpWorkerInterface> {
const worker = await this.createWorker<KcpWorkerInterface>(KcpWorkerInterface)

connInfo.byteCheckMode = GlobalState.get('ByteCheckMode')

if (await worker.init(recvWorkerId, iPort, conv, connInfo)) return worker

await this.destroyWorker(worker.id)

return null
}

async destroyWorker(id: number) {
const { workerList } = this

const worker = workerList.find(w => w.id === id)
if (worker == null) return

Expand Down
8 changes: 6 additions & 2 deletions src/kcpServer/socket/worker/kcpWorker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ export default class KcpWorker extends Worker {
}

private inputKcp(buf: Buffer) {
this.kcp.input(buf)
const ret = this.kcp.input(buf)
if (ret < 0) console.log('kcp input failed with error', ret)

this.updateKcp()
}

Expand Down Expand Up @@ -130,12 +132,13 @@ export default class KcpWorker extends Worker {

this.recvWIPort = iPort

const { token } = info
const { token, byteCheckMode } = info
const kcp = new Kcp(conv, token, this.sendUdpPacket.bind(this))

kcp.setNodelay(true, 8, false)
kcp.setInterval(0)
kcp.setMaxResend(1024)
kcp.setByteCheck(byteCheckMode ?? -1, false)

this.conv = conv
this.kcp = kcp
Expand Down Expand Up @@ -170,6 +173,7 @@ export default class KcpWorker extends Worker {

if (!Packet.isPacket(packet)) {
this.log(LogLevel.WARN, 'message.worker.warn.invalidPacket')
this.log(LogLevel.DEBUG, 'generic.param1', packet.toString('hex'))
continue
}

Expand Down
5 changes: 4 additions & 1 deletion src/kcpServer/socket/worker/recvWorker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface ConnectionInfo {
port: number
connected?: boolean
iPort?: number
byteCheckMode?: number
}

export default class RecvWorker extends Worker {
Expand All @@ -24,7 +25,9 @@ export default class RecvWorker extends Worker {
super()

this.socket = dgram.createSocket('udp4')
this.socket.on('message', (msg, rinfo) => this.emit('UDPMessage', msg, rinfo))
this.socket.on('message', (msg, rinfo) => {
this.emit('UDPMessage', msg, rinfo)
})

this.connInfoMap = {}
this.blockedAddressList = []
Expand Down
77 changes: 77 additions & 0 deletions src/kcpServer/socket/worker/utils/crc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
interface Table {
[i: number]: number
}

function signedCrcTable(): Table {
let c = 0
const table = new Array(256)

for (let n = 0; n < 256; ++n) {
c = n
for (let i = 0; i < 8; i++) {
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1))
}
table[n] = c
}

return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table
}

export const T0 = signedCrcTable()

function sliceBy16Tables(T: Table) {
let c = 0
let v = 0
const table = typeof Int32Array !== 'undefined' ? new Int32Array(4096) : new Array(4096)

for (let n = 0; n < 256; ++n) table[n] = T[n]
for (let n = 0; n < 256; ++n) {
v = T[n]
for (c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF]
}

const out = []
for (let n = 1; n < 16; ++n) {
out[n - 1] = table instanceof Array ? table.slice(n * 256, n * 256 + 256) : table.subarray(n * 256, n * 256 + 256)
}

return out
}

const TT = sliceBy16Tables(T0)
const [
T1, T2, T3, T4, T5,
T6, T7, T8, T9, Ta,
Tb, Tc, Td, Te, Tf
] = TT

function crc32Fast(B: Buffer, C: number, L: number, i: number = 0) {
while (i < L) {
C =
Tf[B[i++] ^ (C & 255)] ^
Te[B[i++] ^ ((C >> 8) & 255)] ^
Td[B[i++] ^ ((C >> 16) & 255)] ^
Tc[B[i++] ^ (C >>> 24)] ^
Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^
T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^
T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]]
}

return { C, L, i }
}

export function crc32(B: Buffer, seed: number = 0): number {
let C = seed ^ -1
let L = B.length
let i = 0

if (L > 15) {
L -= 15; ({ C, L, i } = crc32Fast(B, C, L, i)); L += 15
}

while (i < L) {
C = (C >>> 8) ^ T0[(C ^ B[i++]) & 0xFF]
}

return ~C
}
Loading

0 comments on commit f01b58a

Please sign in to comment.