Files
djhackersdev_minime/src/idz/userdb/decoder/index.ts
T

299 lines
7.3 KiB
TypeScript

import logger from "debug";
import { checkTeamName1, checkTeamName2 } from "./checkTeamName";
import { createProfile1, createProfile2 } from "./createProfile";
import { createTeam1, createTeam2 } from "./createTeam";
import { createAutoTeam1, createAutoTeam2 } from "./createAutoTeam";
import { discoverProfile1, discoverProfile2 } from "./discoverProfile";
import {
load2on2RankingPoints1,
load2on2Info,
load2on2RankingPoints2,
} from "./load2on2";
import {
loadConfigA_1,
loadConfigB_1,
loadConfigA_2,
loadConfigB_2,
} from "./loadConfig";
import { loadEventInfo1, loadEventInfo2 } from "./loadEventInfo";
import { loadGacha1, loadGacha2 } from "./loadGacha";
import { loadGarage1, loadGarage2 } from "./loadGarage";
import {
loadGeneralReward1,
loadGeneralReward2,
loadGeneralReward3,
} from "./loadGeneralReward";
import { loadGhost1, loadGhost2 } from "./loadGhost";
import { loadProfile2, loadProfile3, loadProfile4 } from "./loadProfile";
import { loadRewardTable1, loadRewardTable2 } from "./loadRewardTable";
import { loadServerList } from "./loadServerList";
import { loadStocker1, loadStocker2 } from "./loadStocker";
import { loadTeam1, loadTeam2 } from "./loadTeam";
import {
loadTeamRanking1,
loadTeamRanking2,
loadTeamRanking3,
loadTeamRanking4,
} from "./loadTeamRanking";
import { loadTopTen1 } from "./loadTopTen1";
import { loadTopTen2, loadTopTen3 } from "./loadTopTen2";
import { lockGarage1, lockGarage2 } from "./lockGarage";
import { lockProfile1, lockProfile2 } from "./lockProfile";
import { saveExpedition1, saveExpedition2 } from "./saveExpedition";
import { saveGarage1, saveGarage2 } from "./saveGarage";
import { saveNewCar1, saveNewCar2 } from "./saveNewCar";
import { saveProfile2 } from "./saveProfile2";
import { saveProfile3 } from "./saveProfile3";
import { saveSettings1, saveSettings2 } from "./saveSettings";
import { saveStocker1, saveStocker2 } from "./saveStocker";
import { saveTeamBanner1, saveTeamBanner2 } from "./saveTeamBanner";
import {
saveTimeAttack1,
saveTimeAttack2,
saveTimeAttack3,
} from "./saveTimeAttack";
import { saveTopic1, saveTopic2 } from "./saveTopic";
import { unknownA_1, unknownA_2 } from "./unknownA";
import { unlockProfile1, unlockProfile2 } from "./unlockProfile";
import {
updateProvisionalStoreRank1,
updateProvisionalStoreRank2,
} from "./updateProvisionalStoreRank";
import { updateTeamLeader1, updateTeamLeader2 } from "./updateTeamLeader";
import { updateTeamMember1, updateTeamMember2 } from "./updateTeamMember";
import {
updateStoryClearNum1,
updateStoryClearNum2,
updateStoryClearNum3,
} from "./updateStoryClearNum";
import { Request } from "../request";
import { updateResult } from "./updateResult";
import { updateTeamPoints1, updateTeamPoints2 } from "./updateTeamPoints";
import { updateUiReport1, updateUiReport2 } from "./updateUiReport";
import { updateUserLog1, updateUserLog2 } from "./updateUserLog";
import { lockProfileExtend1, lockProfileExtend2 } from "./lockProfileExtend";
import { BLOCK_SIZE, ClientHello } from "../../common";
import { ByteStream } from "../../../util/stream";
import { saveProfile4 } from "./saveProfile4";
const debug = logger("app:idz:userdb:decoder");
export type ReaderFn = ((buf: Buffer) => Request) & {
msgCode: number;
msgLen: number;
};
function makeReaderMap(funcList: ReaderFn[]): Map<number, ReaderFn> {
const result = new Map<number, ReaderFn>();
for (const fn of funcList) {
result.set(fn.msgCode, fn);
}
return result;
}
// TODO confirm v1.21.00 proto version
const funcList110: ReaderFn[] = [
checkTeamName1,
createAutoTeam1,
createProfile1,
createTeam1,
discoverProfile1,
load2on2RankingPoints1,
loadConfigA_1,
loadConfigB_1,
loadEventInfo1,
loadGacha1,
loadGarage1,
loadGeneralReward1,
loadGhost1,
loadProfile2,
loadRewardTable1,
loadServerList,
loadStocker1,
loadTeam1,
loadTeamRanking1,
lockGarage1,
lockProfile1,
lockProfileExtend1,
loadTopTen1,
saveExpedition1,
saveGarage1,
saveNewCar1,
saveProfile2,
saveSettings1,
saveStocker1,
saveTeamBanner1,
saveTimeAttack1,
saveTopic1,
unknownA_1,
unlockProfile1,
updateProvisionalStoreRank1,
updateResult,
updateStoryClearNum1,
updateTeamLeader1,
updateTeamMember1,
updateTeamPoints1,
updateUiReport1,
updateUserLog1,
];
const funcList130: ReaderFn[] = [
checkTeamName1,
createAutoTeam1,
createProfile1,
createTeam1,
discoverProfile1,
load2on2Info,
updateStoryClearNum2,
updateStoryClearNum3,
loadConfigA_1,
loadConfigB_1,
loadEventInfo1,
loadGacha1,
loadGarage1,
loadGeneralReward2,
loadGhost1,
loadProfile3,
loadRewardTable1,
loadServerList,
loadStocker1,
loadTeam1,
loadTeamRanking1,
loadTeamRanking3,
loadTopTen2,
lockGarage1,
lockProfile1,
lockProfileExtend1,
saveExpedition2,
saveGarage1,
saveNewCar1,
saveProfile3,
saveSettings1,
saveStocker1,
saveTeamBanner1,
saveTimeAttack2,
saveTopic1,
unknownA_1,
unlockProfile1,
updateProvisionalStoreRank1,
updateResult,
updateTeamLeader1,
updateTeamMember1,
updateTeamPoints1,
updateUiReport1,
updateUserLog1,
];
const funcList210: ReaderFn[] = [
checkTeamName2,
createAutoTeam2,
createProfile2,
createTeam2,
discoverProfile2,
load2on2Info,
load2on2RankingPoints2,
updateStoryClearNum3,
loadConfigA_2,
loadConfigB_2,
loadEventInfo2,
loadGacha2,
loadGarage2,
loadGeneralReward3,
loadGhost2,
loadProfile4,
loadRewardTable2,
loadServerList,
loadStocker2,
loadTeam2,
loadTeamRanking2,
loadTeamRanking4,
loadTopTen3,
lockGarage2,
lockProfile2,
lockProfileExtend2,
saveExpedition2,
saveGarage2,
saveNewCar2,
saveProfile4,
saveSettings2,
saveStocker2,
saveTeamBanner2,
saveTimeAttack3,
saveTopic2,
unknownA_2,
unlockProfile2,
updateProvisionalStoreRank2,
updateResult,
updateTeamLeader2,
updateTeamMember2,
updateTeamPoints2,
updateUiReport2,
updateUserLog2,
];
const protocols = new Map<string, Map<number, ReaderFn>>();
protocols.set("110", makeReaderMap(funcList110));
protocols.set("130", makeReaderMap(funcList130));
protocols.set("210", makeReaderMap(funcList210));
async function readRequest(
clientHello: ClientHello,
stm: ByteStream
): Promise<Request | undefined> {
const protocol = protocols.get(clientHello.protocol);
if (protocol === undefined) {
throw new Error(`Unsupported protocol version ${clientHello.protocol}`);
}
const head = await stm.read(BLOCK_SIZE);
if (head.length === 0) {
// Connection closed
return undefined;
}
const msgCode = head.readUInt16LE(0x0000);
const readerFn = protocol.get(msgCode);
if (readerFn === undefined) {
throw new Error(`Message ${msgCode.toString(16)}: Unknown command code`);
}
const tail = await stm.read(readerFn.msgLen - BLOCK_SIZE);
const msg = Buffer.concat([head, tail]);
if (msg.length < readerFn.msgLen) {
throw new Error(`Message ${msgCode.toString(16)}: Truncated read`);
}
if (debug.enabled) {
debug("Raw: %s", msg.toString("hex"));
}
const payload = readerFn(msg);
debug("Payload: %j", payload);
return payload;
}
export default async function* readRequestStream(
clientHello: ClientHello,
stm: ByteStream
) {
while (true) {
const req = await readRequest(clientHello, stm);
if (req === undefined) {
return;
}
yield req;
}
}