Skip to content

Commit

Permalink
修复心跳报错
Browse files Browse the repository at this point in the history
  • Loading branch information
nk-ava committed Jul 13, 2023
1 parent 0c55515 commit ee6154b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 46 deletions.
10 changes: 5 additions & 5 deletions lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class Client extends BaseClient {
this.config = config as Required<Config>
bindInternalListeners.call(this)
this.on("internal.verbose", (verbose, level) => {
const list: Exclude<LogLevel, "off">[] = ["fatal", "mark", "error", "warn", "info", "trace"]
const list: Exclude<LogLevel, "off">[] = ["fatal", "mark", "error", "warn", "info", "debug", "trace"]
this.logger[list[level]](verbose)
})
lock(this, "dir")
Expand All @@ -209,12 +209,12 @@ export class Client extends BaseClient {
hide(this, "_sync_cookie")

let n = 0
this.heartbeat = () => {
this.heartbeat = async () => {
this._calcMsgCntPerMin()
n++
if (n > 10) {
n = 0
this.setOnlineStatus()
await this.setOnlineStatus()
}
}

Expand Down Expand Up @@ -263,8 +263,8 @@ export class Client extends BaseClient {
}

/** 设置在线状态 */
setOnlineStatus(status = this.status || OnlineStatus.Online) {
return setStatus.call(this, status)
async setOnlineStatus(status = this.status || OnlineStatus.Online) {
return await setStatus.call(this, status)
}

/** 设置昵称 */
Expand Down
91 changes: 50 additions & 41 deletions lib/core/base-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const LOGIN_LOCK = Symbol("LOGIN_LOCK")
const HEARTBEAT = Symbol("HEARTBEAT")

export enum VerboseLevel {
Fatal, Mark, Error, Warn, Info, Debug
Fatal, Mark, Error, Warn, Info, Debug, Trace
}

export class ApiRejection {
Expand Down Expand Up @@ -649,8 +649,8 @@ export class BaseClient extends EventEmitter {
.writeBytes(t(0x33))
.writeBytes(t(0x35))
.read()
const pkt = await buildCode2dPacket.call(this, 0x31, 0x11100, body)
this[FN_SEND](pkt).then(payload => {
const {pkt, seq} = await buildCode2dPacket.call(this, 0x31, 0x11100, body)
this[FN_SEND](pkt, 5, "wtlogin.trans_emp", seq).then(payload => {
payload = tea.decrypt(payload.slice(16, -1), this[ECDH].share_key)
const stream = Readable.from(payload, {objectMode: false})
stream.read(54)
Expand Down Expand Up @@ -752,9 +752,9 @@ export class BaseClient extends EventEmitter {
.writeTlv(BUF0)
.writeU16(0)
.read()
const pkt = await buildCode2dPacket.call(this, 0x12, 0x6200, body)
const {pkt, seq} = await buildCode2dPacket.call(this, 0x12, 0x6200, body)
try {
let payload = await this[FN_SEND](pkt)
let payload = await this[FN_SEND](pkt, 5, "wtlogin.trans_emp", seq)
payload = tea.decrypt(payload.slice(16, -1), this[ECDH].share_key)
const stream = Readable.from(payload, {objectMode: false})
stream.read(48)
Expand Down Expand Up @@ -791,14 +791,14 @@ export class BaseClient extends EventEmitter {
return this.sig.seq
}

private [FN_SEND](pkt: Uint8Array, timeout = 5) {
private [FN_SEND](pkt: Uint8Array, timeout = 5, cmd: string, seq: number = 0) {
this.statistics.sent_pkt_cnt++
const seq = this.sig.seq
seq = seq || this.sig.seq
return new Promise((resolve: (payload: Buffer) => void, reject) => {
const id = setTimeout(() => {
this[HANDLERS].delete(seq)
this.statistics.lost_pkt_cnt++
reject(new ApiRejection(-2, `packet timeout (${seq})`))
reject(new ApiRejection(-2, `packet timeout (${seq}: ${cmd})`))
}, timeout * 1000)
this[NET].join(() => {
this[NET].write(pkt, () => {
Expand All @@ -815,10 +815,10 @@ export class BaseClient extends EventEmitter {
private async [FN_SEND_LOGIN](cmd: LoginCmd, body: Buffer) {
if (this[IS_ONLINE] || this[LOGIN_LOCK])
return
const pkt = await buildLoginPacket.call(this, cmd, body)
const {pkt, seq} = await buildLoginPacket.call(this, cmd, body)
try {
this[LOGIN_LOCK] = true
decodeLoginResponse.call(this, await this[FN_SEND](pkt))
decodeLoginResponse.call(this, await this[FN_SEND](pkt, 5, cmd, seq))
} catch (e: any) {
this[LOGIN_LOCK] = false
this.emit("internal.error.network", -2, "server is busy")
Expand All @@ -829,20 +829,25 @@ export class BaseClient extends EventEmitter {
/** 发送一个业务包不等待返回 */
async writeUni(cmd: string, body: Uint8Array, seq = 0) {
this.statistics.sent_pkt_cnt++
if (this.signCmd.includes(cmd)) this[NET].write(await buildUniPktSign.call(this, cmd, body, seq))
else this[NET].write(buildUniPkt.call(this, cmd, body, seq))
if (this.signCmd.includes(cmd)) this[NET].write((await buildUniPktSign.call(this, cmd, body, seq)).pkt)
else this[NET].write(buildUniPkt.call(this, cmd, body, seq).pkt)
}

/** 发送一个业务包并等待返回 */
async sendUni(cmd: string, body: Uint8Array, timeout = 5) {
if (!this[IS_ONLINE]) throw new ApiRejection(-1, `client not online`)
if (this.signCmd.includes(cmd)) return this[FN_SEND](await buildUniPktSign.call(this, cmd, body), timeout)
return this[FN_SEND](buildUniPkt.call(this, cmd, body), timeout)
const {
pkt,
seq
} = this.signCmd.includes(cmd) ? await buildUniPktSign.call(this, cmd, body) : buildUniPkt.call(this, cmd, body);
if (this.signCmd.includes(cmd)) return this[FN_SEND](pkt, timeout, cmd, seq)
return this[FN_SEND](pkt, timeout, cmd, seq)
}
}

async function buildUniPktSign(this: BaseClient, cmd: string, body: Uint8Array, seq = 0) {
let BodySign = await this.getSign(cmd, this.sig.seq, Buffer.from(body));
seq = seq || this[FN_NEXT_SEQ]()
let BodySign = await this.getSign(cmd, seq, Buffer.from(body));
return buildUniPkt.call(this, cmd, body, seq, BodySign);
}

Expand Down Expand Up @@ -870,7 +875,7 @@ function buildUniPkt(this: BaseClient, cmd: string, body: Uint8Array, seq = 0, B
pkt.writeUInt32BE(uin.length + 4, 14)
pkt.fill(uin, 18)
pkt.fill(encrypted, uin.length + 18)
return pkt
return {pkt, seq}
}

const EVENT_KICKOFF = Symbol("EVENT_KICKOFF")
Expand Down Expand Up @@ -980,10 +985,13 @@ async function packetListener(this: BaseClient, pkt: Buffer) {
}
const sso = await parseSso.call(this, decrypted)
this.emit("internal.verbose", `recv:${sso.cmd} seq:${sso.seq}`, VerboseLevel.Debug)
if (this[HANDLERS].has(sso.seq))
if (this[HANDLERS].has(sso.seq)) {
this.emit("internal.verbose", `调用${sso.cmd}:${sso.seq}回调函数`, VerboseLevel.Trace)
this[HANDLERS].get(sso.seq)?.(sso.payload)
else
} else {
this.emit("internal.verbose", `${sso.cmd}:${sso.seq}没有回调函数`, VerboseLevel.Trace)
this.emit("internal.sso", sso.cmd, sso.payload, sso.seq)
}
} catch (e) {
this.emit("internal.verbose", e, VerboseLevel.Error)
}
Expand Down Expand Up @@ -1011,9 +1019,9 @@ async function register(this: BaseClient, logout = false, reflush = false) {
0, null, 1000, 98
])
const body = jce.encodeWrapper({SvcReqRegister}, "PushService", "SvcReqRegister")
const pkt = await buildLoginPacket.call(this, "StatSvc.register", body, 1)
const {pkt, seq} = await buildLoginPacket.call(this, "StatSvc.register", body, 1)
try {
const payload = await this[FN_SEND](pkt, 10)
const payload = await this[FN_SEND](pkt, 10, "StatSvc.register", seq)
if (logout) return
const rsp = jce.decodeWrapper(payload)
const result = rsp[9] ? true : false
Expand All @@ -1024,7 +1032,7 @@ async function register(this: BaseClient, logout = false, reflush = false) {
this[HEARTBEAT] = setInterval(async () => {
syncTimeDiff.call(this).then()
if (typeof this.heartbeat === "function")
await this.heartbeat()
this.heartbeat()
this.sendUni("OidbSvc.0x480_9_IMCore", this.sig.hb480).catch(() => {
this.emit("internal.verbose", "heartbeat timeout", VerboseLevel.Warn)
this.sendUni("OidbSvc.0x480_9_IMCore", this.sig.hb480).catch(() => {
Expand All @@ -1041,8 +1049,8 @@ async function register(this: BaseClient, logout = false, reflush = false) {
}

async function syncTimeDiff(this: BaseClient) {
const pkt = await buildLoginPacket.call(this, "Client.CorrectTime", BUF4, 0)
this[FN_SEND](pkt).then(buf => {
const {pkt, seq} = await buildLoginPacket.call(this, "Client.CorrectTime", BUF4, 0)
this[FN_SEND](pkt, 5, "Client.CorrectTime", seq).then(buf => {
try {
this.sig.time_diff = buf.readInt32BE() - timestamp()
} catch {
Expand Down Expand Up @@ -1074,9 +1082,9 @@ async function refreshToken(this: BaseClient) {
.writeBytes(t(0x202))
.writeBytes(t(0x511))
.read()
const pkt = await buildLoginPacket.call(this, "wtlogin.exchange_emp", body)
const {pkt, seq} = await buildLoginPacket.call(this, "wtlogin.exchange_emp", body)
try {
let payload = await this[FN_SEND](pkt)
let payload = await this[FN_SEND](pkt, 5, "wtlogin.exchange_emp", seq)
payload = tea.decrypt(payload.slice(16, payload.length - 1), this[ECDH].share_key)
const stream = Readable.from(payload, {objectMode: false})
stream.read(2)
Expand Down Expand Up @@ -1111,9 +1119,9 @@ type LoginCmd =
| "Client.CorrectTime"
type LoginCmdType = 0 | 1 | 2

async function buildLoginPacket(this: BaseClient, cmd: LoginCmd, body: Buffer, type: LoginCmdType = 2): Promise<Buffer> {
this[FN_NEXT_SEQ]()
this.emit("internal.verbose", `send:${cmd} seq:${this.sig.seq}`, VerboseLevel.Debug)
async function buildLoginPacket(this: BaseClient, cmd: LoginCmd, body: Buffer, type: LoginCmdType = 2): Promise<{ pkt: Buffer, seq: number }> {
const seq = this[FN_NEXT_SEQ]()
this.emit("internal.verbose", `send:${cmd} seq:${seq}`, VerboseLevel.Debug)
let uin = this.uin, cmdid = 0x810, subappid = this.apk.subid
if (cmd === "wtlogin.trans_emp") {
uin = 0
Expand Down Expand Up @@ -1150,12 +1158,12 @@ async function buildLoginPacket(this: BaseClient, cmd: LoginCmd, body: Buffer, t

let BodySign = BUF0;
if (this.signLoginCmd.includes(cmd)) {
BodySign = await this.getSign(cmd, this.sig.seq, Buffer.from(body));
BodySign = await this.getSign(cmd, seq, Buffer.from(body));
}

let sso = new Writer()
.writeWithLength(new Writer()
.writeU32(this.sig.seq)
.writeU32(seq)
.writeU32(subappid)
.writeU32(subappid)
.writeBytes(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00]))
Expand All @@ -1175,17 +1183,18 @@ async function buildLoginPacket(this: BaseClient, cmd: LoginCmd, body: Buffer, t
sso = tea.encrypt(sso, this.sig.d2key)
else if (type === 2)
sso = tea.encrypt(sso, BUF16)
return new Writer()
.writeWithLength(new Writer()
.writeU32(0x0A)
.writeU8(type)
.writeWithLength(this.sig.d2)
.writeU8(0)
.writeWithLength(String(uin))
.writeBytes(sso)
.read()
)
.read()
return {
pkt: new Writer()
.writeWithLength(new Writer()
.writeU32(0x0A)
.writeU8(type)
.writeWithLength(this.sig.d2)
.writeU8(0)
.writeWithLength(String(uin))
.writeBytes(sso)
.read()
).read(), seq: seq
}
}

async function buildCode2dPacket(this: BaseClient, cmdid: number, head: number, body: Buffer) {
Expand Down

0 comments on commit ee6154b

Please sign in to comment.